MMFX.pas
上传用户:hylc_2004
上传日期:2014-01-23
资源大小:46800k
文件大小:94k
源码类别:

Delphi控件源码

开发平台:

Delphi

  1. {========================================================================}
  2. {=                (c) 1995-98 SwiftSoft Ronald Dittrich                 =}
  3. {========================================================================}
  4. {=                          All Rights Reserved                         =}
  5. {========================================================================}
  6. {=  D 01099 Dresden             = Fax.: +49 (0)351-8037944              =}
  7. {=  Loewenstr.7a                = info@swiftsoft.de                     =}
  8. {========================================================================}
  9. {=  Actual versions on http://www.swiftsoft.de/mmtools.html             =}
  10. {========================================================================}
  11. {=  This code is for reference purposes only and may not be copied or   =}
  12. {=  distributed in any format electronic or otherwise except one copy   =}
  13. {=  for backup purposes.                                                =}
  14. {=                                                                      =}
  15. {=  No Delphi Component Kit or Component individually or in a collection=}
  16. {=  subclassed or otherwise from the code in this unit, or associated   =}
  17. {=  .pas, .dfm, .dcu, .asm or .obj files may be sold or distributed     =}
  18. {=  without express permission from SwiftSoft.                          =}
  19. {=                                                                      =}
  20. {=  For more licence informations please refer to the associated        =}
  21. {=  HelpFile.                                                           =}
  22. {========================================================================}
  23. {=  $Date: 06.09.98 - 13:22:36 $                                        =}
  24. {========================================================================}
  25. unit MMFX;
  26. {$I COMPILER.INC}
  27. interface
  28. uses
  29.     Windows,
  30.     SysUtils,
  31.     MMSystem,
  32.     MMUtils,
  33.     MMRegs,
  34.     MMMulDiv,
  35.     MMMath;
  36. {========================================================================}
  37. const
  38.      { constants for the DataType fields }
  39.      DT_8BIT   = $00;  { x0 b }
  40.      DT_16BIT  = $01;  { x1 b }
  41.      DT_MONO   = $00;  { 0x b }
  42.      DT_STEREO = $02;  { 1x b }
  43.      { constants for channels }
  44.      CH_BOTH   = $00;
  45.      CH_LEFT   = $01;
  46.      CH_RIGHT  = $02;
  47. function GetDataType(pwfx: PWaveFormatEx): integer;
  48. {========================================================================}
  49. const
  50.     FT_NONE        = 0;
  51.     FT_SOFTLOWPASS = 1;
  52.     FT_LOWPASS     = 2;
  53.                            
  54. type
  55.     PSimpleFilter = ^TSimpleFilter;
  56.     TSimpleFilter = packed record
  57.        FilterType: integer;       { FT_NON,FT_SOFTLOWPASS,FT_LOWPASS    }
  58.        DataType  : integer;       { DT_8BIT,DT_16BIT,DT_MONO,DT_STEREO  }
  59.        PrevValL  : SmallInt;      { internal, last sample left channel  }
  60.        PrevValR  : SmallInt;      { internal, last sample right channel }
  61.     end;
  62. function  InitSimpleLowPass(pwfx: PWaveFormatEx): PSimpleFilter;
  63. procedure DoneSimpleLowPass(var pf: PSimpleFilter);
  64. procedure SetSimpleLowPass(pf: PSimpleFilter; FilterTyp: integer);
  65. procedure DoSimpleLowPass(pf: PSimpleFilter; Buf: PChar; Len: Longint); pascal;
  66. {========================================================================}
  67. const
  68.     MaxEchos = 8;
  69. type
  70.     PEcho = ^TEcho;
  71.     TEcho = record
  72.        Delay: Longint;            { delay (ms) for this echo line       }
  73.        Gain : Longint;            { mix volume (%) for this echo        }
  74.     end;
  75.     PEchoArray = ^TEchoArray;
  76.     TEchoArray = array[0..MaxEchos-1] of TEcho;
  77.     PReverbParm = ^TReverbParm;   { Internal for the reverb engine      }
  78.     TReverbParm = record
  79.        Position : Longint;
  80.        Gain     : Longint;
  81.     end;
  82.     PReverb = ^TReverb;
  83.     TReverb = packed record
  84.        InputGain   : Longint;     { Input Gain for the signal (%)       }
  85.        InputPan    : Longint;     { Inp. Pan add 0..100 % to other chan.}
  86.        OutputGain  : Longint;     { mix gain for the echos (%)          }
  87.        OutputFilter: LongBool;    { enable/disable Low pass filter      }
  88.        FeedBack    : Longint;     { Feedback value for reverb (%)       }
  89.        DataType    : integer;     { DT_8BIT,DT_16BIT,DT_MONO,DT_STEREO  }
  90.        SampleRate  : Longint;     { SampleRate for the samples          }
  91.        Count       : integer;     { number of reverbs 0..8              }
  92.        Reverbs     : array[0..MaxEchos-1] of TReverbParm;
  93.        DLineL      : PSmallArray; { Left DelayLine                      }
  94.        DLineR      : PSmallArray; { Right DelayLine                     }
  95.        DLineSize   : Longint;     { max size for DelayLine              }
  96.        DLinePos    : Longint;     { current write position in DelayLine }
  97.        PrevValL    : Longint;     { internal, last sample left channel  }
  98.        PrevValR    : Longint;     { internal, last sample right channel }
  99.        MaxDelay    : integer;     { the maximal allowed delay (ms)      }
  100.     end;
  101. function  InitReverb(pwfx: PWaveFormatEx; MaxDelay: integer): PReverb;
  102. procedure DoneReverb(var prvb: PReverb);
  103. procedure SetReverb(prvb: PReverb; Filter: Boolean; InputGain, InputPan,
  104.                     OutputGain, FeedBack, NumReverbs: integer;
  105.                     NewReverbs: PEchoArray);
  106. function DoReverb(prvb: PReverb; Buf: PChar; Len: Longint): Boolean; pascal;
  107. {========================================================================}
  108. type
  109.     PDelay = ^TDelay;
  110.     TDelay = packed record
  111.        DataType    : integer;     { DT_8BIT,DT_16BIT,DT_MONO,DT_STEREO  }
  112.        SampleRate  : Longint;     { SampleRate for the samples          }
  113.        DLineL      : PSmallArray; { Left DelayLine                      }
  114.        DLineR      : PSmallArray; { Right DelayLine                     }
  115.        DLineSize   : Longint;     { max size for DelayLine              }
  116.        DLinePos    : Longint;     { current write position in DelayLine }
  117.        PositionL   : Longint;     { current read position in DelayLine  }
  118.        PositionR   : Longint;     { current read position in DelayLine  }
  119.        MaxDelay    : integer;     { the maximal allowed delay (ms)      }
  120.     end;
  121. function  InitDelay(pwfx: PWaveFormatEx; MaxDelay: integer): PDelay;
  122. procedure DoneDelay(var pdel: PDelay);
  123. procedure SetDelay(pdel: PDelay; DelayLeft, DelayRight: integer);
  124. procedure DoDelay(pdel: PDelay; Buf: PChar; Len: Longint); pascal;
  125. {========================================================================}
  126. type
  127.     PPhaser = ^TPhaser;
  128.     TPhaser = packed record
  129.        DataType    : integer;     { DT_8BIT,DT_16BIT,DT_MONO,DT_STEREO  }
  130.        Channel     : integer;     { on which channel do the phase shift }
  131.        SampleRate  : Longint;     { SampleRate for the samples          }
  132.        Position    : Longint;     { current outp.position in DelayLine  }
  133.        Delay       : integer;     { the current delay                   }
  134.        DLine       : PSmallArray; { DelayLine                           }
  135.        DLineSize   : Longint;     { max size for DelayLine              }
  136.        DLinePos    : Longint;     { current inp. position in DelayLine  }
  137.        MaxDelay    : integer;     { the maximal allowed delay (ms)      }
  138.        Started     : LongBool;    { new phaser has started              }
  139.        RealTime    : LongBool;    { do special things for realtime phase}
  140.     end;
  141. function  InitPhaser(pwfx: PWaveFormatEx; MaxDelay: integer; RealTime: Boolean): PPhaser;
  142. procedure DonePhaser(var pph: PPhaser);
  143. procedure SetPhaser(pph: PPhaser; iDelay: integer; iChannel: integer);
  144. procedure DoPhaser(pph: PPhaser; Buf: PChar; Len: Longint); pascal;
  145. {========================================================================}
  146. type
  147.     PPhaseShift = ^TPhaseShift;
  148.     TPhaseShift = packed record
  149.        DataType    : integer;     { DT_8BIT,DT_16BIT,DT_MONO,DT_STEREO  }
  150.        SampleRate  : Longint;     { SampleRate for the samples          }
  151.        FeedBack    : Longint;     { Feedback value for phaseshift (%)   }
  152.        DryMix      : Longint;     { dry (unaffected) signal mix (%)     }
  153.        WetMix      : Longint;     { wet (affected) signal mix (%)       }
  154.        Sweep       : Float;       { base frequency of sweep             }
  155.        Rate        : Float;       { rate of sweep in cycles per second  }
  156.        Depth       : Float;       { sweep range in octaves              }
  157.                                   { internal variables                  }
  158.        wp,Min_wp,Max_wp,SweepFact: Float;
  159.        inL1,outL1,inL2,outL2,inL3,outL3,inL4,outL4: Longint;
  160.        inR1,outR1,inR2,outR2,inR3,outR3,inR4,outR4: Longint;
  161.     end;
  162. function  InitPhaseShift(pwfx: PWaveFormatEx): PPhaseShift;
  163. procedure DonePhaseShift(var pps: PPhaseShift);
  164. procedure SetPhaseShift(pps: PPhaseShift; iDry,iWet,iFeedBack: Longint;
  165.                         iSweep,iDepth,iRate: Float);
  166. function  DoPhaseShift(pps: PPhaseShift; Buf: PChar; Len: Longint): Boolean;
  167. {========================================================================}
  168. type
  169.     PFlanger = ^TFlanger;
  170.     TFlanger = packed record
  171.        DataType    : integer;     { DT_8BIT,DT_16BIT,DT_MONO,DT_STEREO  }
  172.        SampleRate  : Longint;     { SampleRate for the samples          }
  173.        FeedBack    : Longint;     { Feedback value for phaseshift (%)   }
  174.        DryMix      : Longint;     { dry (unaffected) signal mix (%)     }
  175.        WetMix      : Longint;     { wet (affected) signal mix (%)       }
  176.        Rate        : Float;       { rate of sweep in cycles per second  }
  177.        Depth       : Float;       { sweep range in octaves              }
  178.        Delay       : integer;     { the current delay (ms)              }
  179.        DLineL      : PSmallArray; { Left DelayLine                      }
  180.        DLineR      : PSmallArray; { Right DelayLine                     }
  181.        DLineSize   : Longint;     { max size for DelayLine              }
  182.        DLinePos    : Longint;     { current position in DelayLine       }
  183.        MaxDelay    : integer;     { the maximal allowed delay (ms)      }
  184.                                   { internal variables                  }
  185.        ep1,ep2: integer;
  186.        Sweep,MinSweep,MaxSweep,Step: Longint;
  187.     end;
  188. function  InitFlanger(pwfx: PWaveFormatEx; MaxDelay: integer): PFlanger;
  189. procedure DoneFlanger(var pfc: PFlanger);
  190. procedure SetFlanger(pfc: PFlanger; iDry,iWet,iFeedBack,
  191.                      iDelay: Longint; iDepth, iRate: Float);
  192. function  DoFlanger(pfc: PFlanger; Buf: PChar; Len: Longint): Boolean;
  193. {========================================================================}
  194. const
  195.      MAX_XTAB = 512;      { crossfade lookup table size for pitch change }
  196. type
  197.     PFadeArray   = ^TFadeArray;
  198.     TFadeArray   = array[0..MAX_XTAB-1] of Float;
  199.     PPitchChange = ^TPitchChange;
  200.     TPitchChange = packed record
  201.        DataType    : integer;      { DT_8BIT,DT_16BIT,DT_MONO,DT_STEREO  }
  202.        SampleRate  : Longint;      { SampleRate for the samples          }
  203.        FeedBack    : Longint;      { Feedback value for phaseshift (%)   }
  204.        DryMix      : Longint;      { dry (unaffected) signal mix (%)     }
  205.        WetMix      : Longint;      { wet (affected) signal mix (%)       }
  206.        Rate        : Float;        { rate of sweep in cycles per second  }
  207.        Depth       : integer;      { sweep range in octaves              }
  208.        Delay       : integer;      { the current delay (ms)              }
  209.        DLineL      : PLongArray;   { Left DelayLine                      }
  210.        DLineR      : PLongArray;   { Right DelayLine                     }
  211.        DLineSize   : Longint;      { max size for DelayLine              }
  212.        MaxDelay    : integer;      { the maximal allowed delay (ms)      }
  213.                                    { internal variables                  }
  214.        fp,ep1,ep2,ep3,ep4: integer;
  215.        MinSweep,MaxSweep: integer;
  216.        Step,XFade,XFadeCnt,Active,ActiveCnt: integer;
  217.        BlendA,BlendB: Float;
  218.        FadeA,FadeB: PFadeArray;
  219.        Fade_Out,Fade_In: TFadeArray;
  220.        Sweep: Longint;
  221.        SweepUp,ChanA: Boolean;
  222.     end;
  223. function  InitPitchChange(pwfx: PWaveFormatEx; MaxDelay: integer): PPitchChange;
  224. procedure DonePitchChange(var ppc: PPitchChange);
  225. procedure SetPitchChange(ppc: PPitchChange; iDry,iWet,iFeedBack,
  226.                          iDelay,iDepth: Longint; iRate: Float);
  227. procedure DoPitchChange(ppc: PPitchChange; Buffer: PChar; Len: Longint); pascal;
  228. implementation
  229. {========================================================================}
  230. function GetDataType(pwfx: PWaveFormatEx): Integer;
  231. begin
  232.    Result := -1;
  233.    if (pwfx <> Nil) and (pwfx^.wFormatTag = WAVE_FORMAT_PCM) then
  234.    begin
  235.       Result := 0;
  236.       if (pwfx^.wBitsPerSample = 16) then Result := Result or DT_16BIT;
  237.       if (pwfx^.nChannels = 2) then Result := Result or DT_STEREO;
  238.    end;
  239. end;
  240. {========================================================================}
  241. { -- Simple Low Pass --                                                  }
  242. {========================================================================}
  243. function InitSimpleLowPass(pwfx: PWaveFormatEx): PSimpleFilter;
  244. begin
  245.    Result := GlobalAllocMem(sizeOf(TSimpleFilter));
  246.    if (Result <> nil) then
  247.    with Result^ do
  248.    begin
  249.       FilterType:= FT_NONE;
  250.       DataType  := GetDataType(pwfx);
  251.       if (DataType and DT_16BIT = DT_16BIT) then
  252.       begin
  253.          PrevValL  := 0;
  254.          PrevValR  := 0;
  255.       end
  256.       else
  257.       begin
  258.          PrevValL  := 128;
  259.          PrevValR  := 128;
  260.       end;
  261.    end;
  262. end;
  263. {========================================================================}
  264. procedure DoneSimpleLowPass(var pf: PSimpleFilter);
  265. begin
  266.    GlobalFreeMem(Pointer(pf));
  267. end;
  268. {========================================================================}
  269. procedure SetSimpleLowPass(pf: PSimpleFilter; FilterTyp: integer);
  270. begin
  271.    if (pf <> nil) then
  272.    with pf^ do
  273.    begin
  274.       FilterType:= FilterTyp;
  275.       if (DataType and DT_16BIT = DT_16BIT) then
  276.       begin
  277.          PrevValL  := 0;
  278.          PrevValR  := 0;
  279.       end
  280.       else
  281.       begin
  282.          PrevValL  := 128;
  283.          PrevValR  := 128;
  284.       end;
  285.    end;
  286. end;
  287. {========================================================================}
  288. { Simple Low Pass Filter                                                 }
  289. {                                                                        }
  290. { Algorithm: Type 1: y(n) := (x(n) + x(n-1))/2                           }
  291. {            Type 2: y(n) := (x(n)*3 + x(n-1))/4                         }
  292. {========================================================================}
  293. {$IFDEF USEASM}
  294. {$L MMSLOWL.OBJ}
  295. {$F+}
  296. procedure DoSimpleLowPass(pf: PSimpleFilter; Buf: PChar; Len: Longint); external;
  297. {$F-}
  298. {$ELSE}
  299. procedure DoSimpleLowPass(pf: PSimpleFilter; Buf: PChar; Len: Longint);
  300. var
  301.    pW: PSmallInt;
  302.    pB: PByte;
  303. begin
  304.    if (pf <> nil) then
  305.    with pf^ do
  306.    case FilterType of
  307.         FT_SOFTLOWPASS:
  308.         if (DataType and DT_STEREO = DT_STEREO) then  { Stereo }
  309.         begin
  310.            if (DataType and DT_16BIT = DT_16BIT) then { 16-bit }
  311.            begin
  312.               pW := PSmallInt(Buf);
  313.               while (Len > 0) do
  314.               begin
  315.                  pW^ := (Longint(PrevValL)+pW^+pW^+pW^) shr 2;
  316.                  PrevValL := pW^;
  317.                  inc(pW);
  318.                  pW^ := (Longint(PrevValR)+pW^+pW^+pW^) shr 2;
  319.                  PrevValR := pW^;
  320.                  inc(pW);
  321.                  dec(Len,2*sizeOf(SmallInt));
  322.               end;
  323.            end
  324.            else
  325.            begin                                      { 8-bit }
  326.               pB := PByte(Buf);
  327.               while (Len > 0) do
  328.               begin
  329.                  pB^ := (PrevValL+pB^+pB^+pB^) shr 2;
  330.                  PrevValL := pB^;
  331.                  inc(pB);
  332.                  pB^ := (PrevValR+pB^+pB^+pB^) shr 2;
  333.                  PrevValR := pB^;
  334.                  inc(pB);
  335.                  dec(Len,2*sizeOf(Byte));
  336.               end;
  337.            end;
  338.         end
  339.         else                                          { Mono }
  340.         begin
  341.            if (DataType and DT_16BIT = DT_16BIT) then { 16-bit }
  342.            begin
  343.               pW := PSmallInt(Buf);
  344.               while (Len > 0) do
  345.               begin
  346.                  pW^ := (Longint(PrevValL)+pW^+pW^+pW^)shr 2;
  347.                  PrevValL := pW^;
  348.                  inc(pW);
  349.                  dec(Len,sizeOf(SmallInt));
  350.               end;
  351.            end
  352.            else                                       { 8-bit }
  353.            begin
  354.               pB := PByte(Buf);
  355.               while (Len > 0) do
  356.               begin
  357.                  pB^ := (PrevValL+pB^+pB^+pB^) shr 2;
  358.                  PrevValL := pB^;
  359.                  inc(pB);
  360.                  dec(Len,sizeOf(Byte));
  361.               end;
  362.            end;
  363.         end;
  364.         FT_LOWPASS:
  365.         if (DataType and DT_STEREO = DT_STEREO) then  { Stereo }
  366.         begin
  367.            if (DataType and DT_16BIT = DT_16BIT) then { 16-bit }
  368.            begin
  369.               Len := (Len div 4) * 4;
  370.               pW := PSmallInt(Buf);
  371.               while Len > 0 do
  372.               begin
  373.                  pW^ := (Longint(PrevValL)+pW^) shr 1;
  374.                  PrevValL := pW^;
  375.                  inc(pW);
  376.                  pW^ := (Longint(PrevValR)+pW^) shr 1;
  377.                  PrevValR := pW^;
  378.                  inc(pW);
  379.                  dec(Len,2*sizeOf(SmallInt));
  380.               end;
  381.            end
  382.            else                               { 8 bit }
  383.            begin
  384.               Len := Len and $FFFE;
  385.               pB := PByte(Buf);
  386.               while (Len > 0) do
  387.               begin
  388.                  pB^ := (PrevValL+pB^)shr 1;
  389.                  PrevValL := pB^;
  390.                  inc(pB);
  391.                  pB^ := (PrevValR+pB^)shr 1;
  392.                  PrevValR := pB^;
  393.                  inc(pB);
  394.                  dec(Len,2*sizeOf(Byte));
  395.               end;
  396.            end;
  397.         end
  398.         else                                          { Mono }
  399.         begin
  400.            if (DataType and DT_16BIT = DT_16BIT) then { 16-bit }
  401.            begin
  402.               Len := Len and $FFFE;
  403.               pW := PSmallInt(Buf);
  404.               while (Len > 0) do
  405.               begin
  406.                  pW^ := (Longint(PrevValL)+pW^) shr 1;
  407.                  PrevValL := pW^;
  408.                  inc(pW);
  409.                  dec(Len,sizeOf(SmallInt));
  410.               end;
  411.            end
  412.            else
  413.            begin                                      { 8-bit }
  414.               pB := PByte(Buf);
  415.               while (Len > 0) do
  416.               begin
  417.                  pB^ := (PrevValL+pB^) shr 1;
  418.                  PrevValL := pB^;
  419.                  inc(pB);
  420.                  dec(Len,sizeOf(Byte));
  421.               end;
  422.            end;
  423.         end;
  424.    end;
  425. end;
  426. {$ENDIF}
  427. {========================================================================}
  428. { -- Reverb --                                                           }
  429. {========================================================================}
  430. function InitReverb(pwfx: PWaveFormatEx; MaxDelay: integer): PReverb;
  431. var
  432.    i: integer;
  433. begin
  434.    Result := GlobalAllocMem(SizeOf(TReverb));
  435.    if (Result <> nil) then
  436.    begin
  437.       {$IFNDEF USEASM}
  438.       MaxDelay := Min(MaxDelay,500);
  439.       {$ENDIF}
  440.       Result^.MaxDelay := MaxDelay;
  441.       with Result^ do
  442.       begin
  443.          DataType    := GetDataType(pwfx);
  444.          SampleRate  := pwfx^.nSamplesPerSec;
  445.          Count       := 0;
  446.          InputGain   := 100 * 256 div 100;
  447.          InputPan    := 50 * 256 div 100;
  448.          OutputGain  := 50 * 256 div 100;
  449.          OutputFilter:= False;
  450.          FeedBack    := 0;
  451.          DLineL      := nil;
  452.          DLineR      := nil;
  453.          DLinePos    := 0;
  454.          if (DataType and DT_16BIT = DT_16BIT) then
  455.          begin
  456.             PrevValL  := 0;
  457.             PrevValR  := 0;
  458.          end
  459.          else
  460.          begin
  461.             PrevValL  := 128;
  462.             PrevValR  := 128;
  463.          end;
  464.                                             { Calculate delay line size }
  465.          DLineSize := SampleRate*MaxDelay div 1000;
  466.          i := 0;
  467.          while DLineSize > 2048 do
  468.          begin
  469.             DLineSize := DLineSize shr 1;
  470.             inc(i);
  471.          end;
  472.          DLineSize := 2048;
  473.          while i > 0 do
  474.          begin
  475.             DLineSize := DLineSize shl 1;
  476.             dec(i);
  477.          end;
  478.          DLineL := GlobalAllocMem(DLineSize*sizeOf(SmallInt));
  479.          if (DataType and DT_STEREO = DT_STEREO) then
  480.              DLineR := GlobalAllocMem(DLineSize*sizeOf(SmallInt));
  481.          if (DLineL = nil) or
  482.             ((DLineR = nil) and (DataType and DT_STEREO = DT_STEREO)) then
  483.          begin
  484.             DoneReverb(Result);
  485.          end;
  486.       end;
  487.    end;
  488. end;
  489. {========================================================================}
  490. procedure DoneReverb(var prvb: PReverb);
  491. begin
  492.    if (prvb <> nil) then
  493.    begin
  494.       GlobalFreeMem(Pointer(prvb^.DLineL));
  495.       GlobalFreeMem(Pointer(prvb^.DLineR));
  496.       GlobalFreeMem(Pointer(prvb));
  497.    end;
  498. end;
  499. {========================================================================}
  500. procedure SetReverb(prvb: PReverb; Filter: Boolean; InputGain, InputPan,
  501.                     Outputgain, FeedBack, NumReverbs: integer;
  502.                     NewReverbs: PEchoArray);
  503. var
  504.    i: integer;
  505. begin
  506.    if (prvb <> nil) then
  507.    begin
  508.       with prvb^ do
  509.       begin
  510.          if (DataType and DT_16BIT = DT_16BIT) then
  511.          begin
  512.             PrevValL  := 0;
  513.             PrevValR  := 0;
  514.          end
  515.          else
  516.          begin
  517.             PrevValL  := 128;
  518.             PrevValR  := 128;
  519.          end;
  520.          if (NumReverbs > 8) or (NumReverbs < 0) then exit;
  521.          for i := 0 to NumReverbs-1 do { Check max delay for delay line }
  522.          begin
  523.             if (NewReverbs^[i].Delay > MaxDelay) then
  524.                NewReverbs^[i].Delay := MaxDelay;
  525.          end;
  526.          if (DLineSize > 0) then
  527.          begin
  528.             FillChar(DLineL^,2*DLineSize,0);        { Clear delay lines }
  529.             if (DataType and DT_STEREO = DT_STEREO) then
  530.                FillChar(DLineR^,2*DLineSize,0);
  531.          end;
  532.          for i := 0 to NumReverbs-1 do                 { Adjust reverbs }
  533.          begin
  534.             Reverbs[i].Position := DLineSize-Max(Long(SampleRate)*NewReverbs^[i].Delay div 1000,1);
  535.             Reverbs[i].Gain := NewReverbs^[i].Gain * 256 div 100;
  536.          end;
  537.          Count := NumReverbs;
  538.          DLinePos := 0;
  539.       end;
  540.       prvb^.InputGain:= InputGain * 256 div 100;
  541.       prvb^.InputPan := InputPan * 256 div 100;
  542.       prvb^.OutputGain := OutputGain * 256 div 100;
  543.       prvb^.OutputFilter := Filter;
  544.       prvb^.Feedback := Feedback * 256 div 100;
  545.    end;
  546. end;
  547. {========================================================================}
  548. {                                           FeedBack                     }
  549. {       ______  +--------------------<---------------------------+       }
  550. {  IN  | INP  | |                           Direct Signal  ___   |       }
  551. {  --->| GAIN |-+-------------------->------------------->| + |  |       }
  552. {      |______| |                                         |   |  | OUT   }
  553. {               |                                         |   |--+--->   }
  554. {      +--------+                                         | + |          }
  555. {      |    _________     _________        ___            |___|          }
  556. {      |   |         |   |         |  * a |   |    ______   |            }
  557. {      +-->| Delay 1 |-->| Gain 1  |----->| + |   | OUT  |  |            }
  558. {      |   |_________|   |_________|      |   |-->| GAIN |--+            }
  559. {      |    _________     _________       |   |   |______|               }
  560. {      |   |         |   |         |  * b |   |                          }
  561. {      +-->| Delay 2 |-->| Gain 2  |----->| + |                          }
  562. {      |   |_________|   |_________|      |   |                          }
  563. {      |                                  |   |                          }
  564. {      +--> ....                          |   |                          }
  565. {========================================================================}
  566. {$IFDEF USEASM}
  567. {$L MMREVBL.OBJ}
  568. {$F+}
  569. var
  570.    Reverb: TReverb;
  571.    PrevvalOutL: Longint;
  572.    PrevvalOutR: Longint;
  573. function DoReverb(prvb: PReverb; Buf: PChar; Len: Longint): Boolean; external;
  574. {$F-}
  575. {$ELSE}
  576. function DoReverb(prvb: PReverb; Buf: PChar; Len: Longint): Boolean;
  577. var
  578.    mask,t: integer;
  579.    pW: PSmallint;
  580.    pB: PByte;
  581.    revval,outvalL,outvalR,tempval: Longint;
  582. begin
  583.    { returns true on internal overflow }
  584.    Result := False;
  585.    if (prvb <> nil) and (prvb^.Count > 0) then
  586.    with prvb^ do
  587.    begin
  588.       mask := DLineSize-1;         { Mask to prevent delay line overflow }
  589.       if (DataType and DT_STEREO = DT_STEREO) then    { stereo }
  590.       begin
  591.          if (DataType and DT_16BIT = DT_16BIT) then   { 16-bit }
  592.          begin
  593.             Len := Len div 4 * 4;
  594.             pW := PSmallint(Buf);
  595.             while (Len > 0) do
  596.             begin                                     { Process left }
  597.                outvalL := sar(pW^*InputGain,8);
  598.                outvalR := sar(PSmallInt(PChar(pW)+sizeOf(SmallInt))^*InputGain,8);
  599.                revval := 0;
  600.                for t := 0 to Count-1 do
  601.                begin
  602.                   revval := revval + (Reverbs[t].Gain*DLineL^[Reverbs[t].Position]);
  603.                end;
  604.                revval := sar(PrevValL + sar(revval,8),1);
  605.                PrevValL := revval;
  606.                tempval := outvalL + sar(outvalR*InputPan,8) + sar(revval*Feedback,8);
  607.                revval := outvalL + sar(revval*OutputGain,8);
  608.                if (revval > 32767) then
  609.                begin
  610.                   Result := True;
  611.                   revval := 32767
  612.                end
  613.                else if (revval < -32767) then
  614.                begin
  615.                   Result := True;
  616.                   revval := -32767;
  617.                end;
  618.                if (tempval > 32767) then
  619.                begin
  620.                   Result := True;
  621.                   tempval := 32767;
  622.                end
  623.                else if (tempval < -32767) then
  624.                begin
  625.                   Result := True;
  626.                   tempval := -32767;
  627.                end;
  628.                DLineL^[DLinePos] := tempval;
  629.                pW^ := SmallInt(revval);
  630.                inc(pW);
  631.                                                       { Process right }
  632.                revval := 0;
  633.                for t := 0 to Count-1 do
  634.                begin
  635.                   revval := revval + (reverbs[t].gain*DLineR^[reverbs[t].Position]);
  636.                   Reverbs[t].Position := (reverbs[t].Position + 1) and mask;
  637.                end;
  638.                revval := sar(PrevValR+sar(revval,8),1);
  639.                PrevValR := revval;
  640.                tempval := outvalR + sar(outvalL*InputPan,8) + sar(revval*Feedback,8);
  641.                revval := outvalR + sar(revval*OutputGain,8);
  642.                if (revval > 32767) then
  643.                begin
  644.                   Result := True;
  645.                   revval := 32767
  646.                end
  647.                else if (revval < -32767) then
  648.                begin
  649.                   Result := True;
  650.                   revval := -32767;
  651.                end;
  652.                if (tempval > 32767) then
  653.                begin
  654.                   Result := True;
  655.                   tempval := 32767;
  656.                end
  657.                else if (tempval < -32767) then
  658.                begin
  659.                   Result := True;
  660.                   tempval := -32767;
  661.                end;
  662.                DLineR^[DLinePos] := tempval;
  663.                pW^ := revval;
  664.                inc(pW);
  665.                DLinePos := (DLinePos + 1) and mask;
  666.                dec(Len,2*sizeOf(SmallInt));
  667.             end;
  668.          end
  669.          else                                         { 8-bit stereo }
  670.          begin
  671.             Len := Len and $FFFE;
  672.             pB := PByte(Buf);
  673.             while (Len > 0) do
  674.             begin                                     { Process left }
  675.                outvalL := sar(((pB^-128) shl 8)*InputGain,8);
  676.                outvalR := sar(((PByte(PChar(pB)+sizeOf(Byte))^-128)shl 8)*InputGain,8);
  677.                revval := 0;
  678.                for t := 0 to Count-1 do
  679.                begin
  680.                   revval := revval + (reverbs[t].gain*DLineL^[reverbs[t].position]);
  681.                end;
  682.                revval := sar(PrevValL+sar(revval,8),1);
  683.                PrevValL := revval;
  684.                tempval := outvalL+sar(outvalR*InputPan,8)+sar(revval*Feedback,8);
  685.                revval := outvalL + sar(revval*OutputGain,8);
  686.                if (revval > 32767) then
  687.                begin
  688.                   Result := True;
  689.                   revval := 32767
  690.                end
  691.                else if (revval < -32767) then
  692.                begin
  693.                   Result := True;
  694.                   revval := -32767;
  695.                end;
  696.                if (tempval > 32767) then
  697.                begin
  698.                   Result := True;
  699.                   tempval := 32767;
  700.                end
  701.                else if (tempval < -32767) then
  702.                begin
  703.                   Result := True;
  704.                   tempval := -32767;
  705.                end;
  706.                DLineL^[DLinePos] := tempval;
  707.                pB^ := (revval shr 8) + 128;
  708.                inc(pB);
  709.                                                       { Process right }
  710.                revval := 0;
  711.                for t := 0 to Count-1 do
  712.                begin
  713.                   revval := revval + (reverbs[t].gain*DLineR^[reverbs[t].position]);
  714.                   reverbs[t].position := (reverbs[t].position + 1) and mask;
  715.                end;
  716.                revval := sar(PrevValR+sar(revval,8),1);
  717.                PrevValR := revval;
  718.                tempval := outvalR+sar(outvalL*InputPan,8)+sar(revval*Feedback,8);
  719.                revval := outvalR + sar(revval*OutputGain,8);
  720.                if (revval > 32767) then
  721.                begin
  722.                   Result := True;
  723.                   revval := 32767
  724.                end
  725.                else if (revval < -32767) then
  726.                begin
  727.                   Result := True;
  728.                   revval := -32767;
  729.                end;
  730.                if (tempval > 32767) then
  731.                begin
  732.                   Result := True;
  733.                   tempval := 32767;
  734.                end
  735.                else if (tempval < -32767) then
  736.                begin
  737.                   Result := True;
  738.                   tempval := -32767;
  739.                end;
  740.                DLineR^[DLinePos] := tempval;
  741.                pB^ := (revval shr 8) + 128;
  742.                inc(pB);
  743.                DLinePos := (DLinePos+1) and mask;
  744.                dec(Len,2*sizeOf(Byte));
  745.             end;
  746.          end;
  747.       end
  748.       else                                            { Mono reverb }
  749.       begin
  750.          if (dataType and DT_16BIT = DT_16BIT) then   { 16-bit Mono }
  751.          begin
  752.             Len := Len and $FFFE;
  753.             pW := PSmallint(Buf);
  754.             while (Len > 0) do
  755.             begin
  756.                outvalL := sar(pW^*InputGain,8);
  757.                revval := 0;
  758.                for t := 0 to Count-1 do
  759.                begin
  760.                   revval := revval + (reverbs[t].gain*DLineL^[reverbs[t].position]);
  761.                   reverbs[t].position := (reverbs[t].position + 1) and mask;
  762.                end;
  763.                revval := sar(PrevValL+sar(revval,8),1);
  764.                PrevValL := revval;
  765.                tempval := outvalL+sar(revval*Feedback,8);
  766.                revval := outvalL + sar(revval*OutputGain,8);
  767.                if (revval > 32767) then
  768.                begin
  769.                   Result := True;
  770.                   revval := 32767
  771.                end
  772.                else if (revval < -32767) then
  773.                begin
  774.                   Result := True;
  775.                   revval := -32767;
  776.                end;
  777.                if (tempval > 32767) then
  778.                begin
  779.                   Result := True;
  780.                   tempval := 32767;
  781.                end
  782.                else if (tempval < -32767) then
  783.                begin
  784.                   Result := True;
  785.                   tempval := -32767;
  786.                end;
  787.                DLineL^[DLinePos] := tempval;
  788.                pW^ := revval;
  789.                inc(pW);
  790.                DLinePos := (DLinePos+1) and mask;
  791.                dec(Len,sizeOf(SmallInt));
  792.             end;
  793.          end
  794.          else
  795.          begin
  796.             pB := PByte(Buf);                         { 8-bit Mono }
  797.             while (Len > 0) do
  798.             begin
  799.                outvalL := sar(((pB^-128) shl 8)*InputGain,8);
  800.                revval := 0;
  801.                for t := 0 to Count-1 do
  802.                begin
  803.                   revval := revval + (reverbs[t].gain*DLineL^[reverbs[t].position]);
  804.                   reverbs[t].position := (reverbs[t].position + 1) and mask;
  805.                end;
  806.                revval := sar(PrevValL+sar(revval,8),1);
  807.                PrevValL := revval;
  808.                tempval := outvalL+sar(revval*Feedback,8);
  809.                revval := outvalL + sar(revval*OutputGain,8);
  810.                if (revval > 32767) then
  811.                begin
  812.                   Result := True;
  813.                   revval := 32767
  814.                end
  815.                else if (revval < -32767) then
  816.                begin
  817.                   Result := True;
  818.                   revval := -32767;
  819.                end;
  820.                if (tempval > 32767) then
  821.                begin
  822.                   Result := True;
  823.                   tempval := 32767;
  824.                end
  825.                else if (tempval < -32767) then
  826.                begin
  827.                   Result := True;
  828.                   tempval := -32767;
  829.                end;
  830.                DLineL^[DLinePos] := tempval;
  831.                pB^ := (revval shr 8) + 128;
  832.                inc(pB);
  833.                DLinePos := (DLinePos+1) and mask;
  834.                dec(Len,sizeOf(Byte));
  835.             end;
  836.          end;
  837.       end;
  838.    end;
  839. end;
  840. {$ENDIF}
  841. {========================================================================}
  842. { -- Delay --                                                            }
  843. {========================================================================}
  844. function InitDelay(pwfx: PWaveFormatEx; MaxDelay: integer): PDelay;
  845. var
  846.    i: integer;
  847. begin
  848.    Result := GlobalAllocMem(SizeOf(TDelay));
  849.    if (Result <> nil) then
  850.    begin
  851.       {$IFNDEF USEASM}
  852.       MaxDelay := Min(MaxDelay,500);
  853.       {$ENDIF}
  854.       Result^.MaxDelay := MaxDelay;
  855.       with Result^ do
  856.       begin
  857.          DataType    := GetDataType(pwfx);
  858.          SampleRate  := pwfx^.nSamplesPerSec;
  859.          DLineL      := nil;
  860.          DLineR      := nil;
  861.          DLinePos    := 0;
  862.                                             { Calculate delay line size }
  863.          DLineSize := SampleRate*MaxDelay div 1000;
  864.          i := 0;
  865.          while DLineSize > 2048 do
  866.          begin
  867.             DLineSize := DLineSize shr 1;
  868.             inc(i);
  869.          end;
  870.          DLineSize := 2048;
  871.          while i > 0 do
  872.          begin
  873.             DLineSize := DLineSize shl 1;
  874.             dec(i);
  875.          end;
  876.          DLineL := GlobalAllocMem(DLineSize*sizeOf(SmallInt));
  877.          if (DataType and DT_STEREO = DT_STEREO) then
  878.              DLineR := GlobalAllocMem(DLineSize*sizeOf(SmallInt));
  879.          if (DLineL = nil) or
  880.             ((DLineR = nil) and (DataType and DT_STEREO = DT_STEREO)) then
  881.          begin
  882.             DoneDelay(Result);
  883.          end;
  884.       end;
  885.    end;
  886. end;
  887. {========================================================================}
  888. procedure DoneDelay(var pdel: PDelay);
  889. begin
  890.    if (pdel <> nil) then
  891.    begin
  892.       GlobalFreeMem(Pointer(pdel^.DLineL));
  893.       GlobalFreeMem(Pointer(pdel^.DLineR));
  894.       GlobalFreeMem(Pointer(pdel));
  895.    end;
  896. end;
  897. {========================================================================}
  898. procedure SetDelay(pdel: PDelay; DelayLeft, DelayRight: integer);
  899. begin
  900.    if (pdel <> nil) then
  901.    begin
  902.       with pdel^ do
  903.       begin
  904.          { Check max delay for delay line }
  905.          if (DelayLeft > MaxDelay) then
  906.              DelayRight := MaxDelay;
  907.          if (DelayRight > MaxDelay) then
  908.              DelayRight := MaxDelay;
  909.          if (DLineSize > 0) then
  910.          begin
  911.             FillChar(DLineL^,DLineSize*sizeOf(SmallInt),0);        { Clear delay lines }
  912.             if (DataType and DT_STEREO = DT_STEREO) then
  913.                FillChar(DLineR^,DLineSize*sizeOf(SmallInt),0);
  914.          end;
  915.          PositionL := DLineSize-Max(Long(SampleRate)*DelayLeft div 1000,1);
  916.          PositionR := DLineSize-Max(Long(SampleRate)*DelayRight div 1000,1);
  917.          DLinePos := 0;
  918.       end;
  919.    end;
  920. end;
  921. {========================================================================}
  922. {$IFDEF USEASM}
  923. {$L MMDELL.OBJ}
  924. {$F+}
  925. var
  926.    Delay: TDelay;
  927. procedure DoDelay(pdel: PDelay; Buf: PChar; Len: Longint); external;
  928. {$F-}
  929. {$ELSE}
  930. procedure DoDelay(pdel: PDelay; Buf: PChar; Len: Longint);
  931. var
  932.    mask: integer;
  933.    pW: PSmallint;
  934.    pB: PByte;
  935. begin
  936.    if (pdel <> nil) then
  937.    with pdel^ do
  938.    begin
  939.       mask := DLineSize-1;         { Mask to prevent delay line overflow }
  940.       if (DataType and DT_STEREO = DT_STEREO) then    { stereo }
  941.       begin
  942.          if (DataType and DT_16BIT = DT_16BIT) then   { 16-bit }
  943.          begin
  944.             Len := Len div 4 * 4;
  945.             pW := PSmallint(Buf);
  946.             while (Len > 0) do
  947.             begin                                     { Process left }
  948.                DLineL^[DLinePos] := pW^;
  949.                pW^ := DLineL^[PositionL];
  950.                PositionL := (PositionL + 1) and mask;
  951.                inc(pW);
  952.                                                       { Process right }
  953.                DLineR^[DLinePos] := pW^;
  954.                pW^ := DLineR^[PositionR];
  955.                PositionR := (PositionR + 1) and mask;
  956.                inc(pW);
  957.                DLinePos := (DLinePos + 1) and mask;
  958.                dec(Len,2*sizeOf(SmallInt));
  959.             end;
  960.          end
  961.          else                                         { 8-bit stereo }
  962.          begin
  963.             Len := Len and $FFFE;
  964.             pB := PByte(Buf);
  965.             while (Len > 0) do
  966.             begin                                     { Process left }
  967.                DLineL^[DLinePos] := (pB^-128) shl 8;
  968.                pB^ := (DLineL^[PositionL] shr 8)+128;
  969.                PositionL := (PositionL + 1) and mask;
  970.                inc(pB);
  971.                                                       { Process right }
  972.                DLineR^[DLinePos] := (pB^-128) shl 8;
  973.                pB^ := (DLineR^[PositionR] shr 8)+128;
  974.                PositionR := (PositionR + 1) and mask;
  975.                inc(pB);
  976.                DLinePos := (DLinePos + 1) and mask;
  977.                dec(Len,2*sizeOf(Byte));
  978.             end;
  979.          end;
  980.       end
  981.       else                                            { Mono reverb }
  982.       begin
  983.          if (dataType and DT_16BIT = DT_16BIT) then   { 16-bit Mono }
  984.          begin
  985.             Len := Len and $FFFE;
  986.             pW := PSmallint(Buf);
  987.             while (Len > 0) do
  988.             begin
  989.                DLineL^[DLinePos] := pW^;
  990.                pW^ := DLineL^[PositionL];
  991.                PositionL := (PositionL + 1) and mask;
  992.                inc(pW);
  993.                DLinePos := (DLinePos + 1) and mask;
  994.                dec(Len,sizeOf(SmallInt));
  995.             end;
  996.          end
  997.          else
  998.          begin
  999.             pB := PByte(Buf);                         { 8 -bit Mono }
  1000.             while (Len > 0) do
  1001.             begin
  1002.                DLineL^[DLinePos] := (pB^-128) shl 8;
  1003.                pB^ := (DLineL^[PositionL] shr 8)+128;
  1004.                PositionL := (PositionL + 1) and mask;
  1005.                inc(pB);
  1006.                DLinePos := (DLinePos + 1) and mask;
  1007.                dec(Len,sizeOf(Byte));
  1008.             end;
  1009.          end;
  1010.       end;
  1011.    end;
  1012. end;
  1013. {$ENDIF}
  1014. {========================================================================}
  1015. { -- Phaser --                                                           }
  1016. {========================================================================}
  1017. function InitPhaser(pwfx: PWaveFormatEx; MaxDelay: integer; RealTime: Boolean): PPhaser;
  1018. var
  1019.    i: integer;
  1020. begin
  1021.    Result := GlobalAllocMem(SizeOf(TPhaser));
  1022.    if (Result <> nil) then
  1023.    begin
  1024.       {$IFNDEF USEASM}
  1025.       MaxDelay := Min(MaxDelay,500);
  1026.       {$ENDIF}
  1027.       Result^.MaxDelay := MaxDelay;
  1028.       Result^.RealTime := RealTime;
  1029.       with Result^ do
  1030.       begin
  1031.          DataType    := GetDataType(pwfx);
  1032.          Channel     := CH_BOTH;
  1033.          SampleRate  := pwfx^.nSamplesPerSec;
  1034.          Delay       := 0;
  1035.          Position    := 0;
  1036.          Started     := False;
  1037.          DLine       := nil;
  1038.          DLinePos    := -1;
  1039.                                             { Calculate delay line size }
  1040.          DLineSize := SampleRate*MaxDelay div 1000;
  1041.          i := 0;
  1042.          while DLineSize > 2048 do
  1043.          begin
  1044.             DLineSize := DLineSize shr 1;
  1045.             inc(i);
  1046.          end;
  1047.          DLineSize := 2048;
  1048.          while i > 0 do
  1049.          begin
  1050.             DLineSize := DLineSize shl 1;
  1051.             dec(i);
  1052.          end;
  1053.          DLine := GlobalAllocMem(2*DLineSize);
  1054.          if (DLine = nil) then
  1055.          begin
  1056.             DonePhaser(Result);
  1057.          end;
  1058.       end;
  1059.    end;
  1060. end;
  1061. {========================================================================}
  1062. procedure DonePhaser(var pph: PPhaser);
  1063. begin
  1064.    if (pph <> nil) then
  1065.    begin
  1066.       GlobalFreeMem(Pointer(pph^.DLine));
  1067.       GlobalFreeMem(Pointer(pph));
  1068.    end;
  1069. end;
  1070. {========================================================================}
  1071. procedure SetPhaser(pph: PPhaser; iDelay: integer; iChannel: integer);
  1072. var
  1073.    Silence: integer;
  1074. begin
  1075.    if (pph <> nil) then
  1076.    begin
  1077.       with pph^ do
  1078.       begin
  1079.          Delay := Min(iDelay,MaxDelay);
  1080.          Channel := iChannel;
  1081.          if (DLineSize > 0) then
  1082.          begin
  1083.             if (DataType and DT_16BIT = DT_16BIT) then
  1084.                 Silence := 0
  1085.             else
  1086.                 Silence := 128;
  1087.             FillChar(DLine^,2*DLineSize,Silence);      { Clear delay line }
  1088.          end;
  1089.                                                        { Adjust phaser }
  1090.          Position := DLineSize-Long(SampleRate)*Delay div 1000-1;
  1091.          DLinePos := -1;
  1092.          if RealTime then Started := True;
  1093.       end;
  1094.    end;
  1095. end;
  1096. {========================================================================}
  1097. {$IFDEF USEASM}
  1098. {$L MMPHASL.OBJ}
  1099. {$F+}
  1100. procedure DoPhaser(pph: PPhaser; Buf: PChar; Len: Longint); external;
  1101. {$F-}
  1102. {$ELSE}
  1103. procedure DoPhaser(pph: PPhaser; Buf: PChar; Len: Longint);
  1104. var
  1105.    pW: PSmallInt;
  1106.    pB: PByte;
  1107.    mask: integer;
  1108. begin
  1109.    if (pph <> nil) and (pph^.Delay > 0) and
  1110.       (pph^.DataType and DT_STEREO = DT_STEREO) and
  1111.       (pph^.Channel <> 0) then
  1112.    with pph^ do
  1113.    begin
  1114.       mask := DLineSize-1;
  1115.       if (DataType and DT_16BIT = DT_16BIT) then { 16-bit }
  1116.       begin
  1117.          Len := (Len div 4) * 4;
  1118.          pW := PSmallInt(Buf);
  1119.          if (Channel and CH_RIGHT = CH_RIGHT) then inc(pW);
  1120.          while Len > 0 do
  1121.          begin
  1122.             DLinePos := (DLinePos+1) and mask;
  1123.             DLine^[DLinePos] := pW^;
  1124.             Position := (Position + 1) and mask;
  1125.             if not Started then pW^ := DLine^[Position]
  1126.             else if (Position = 0) then Started := False;
  1127.             inc(pW,2);
  1128.             dec(Len,2*sizeOf(SmallInt));
  1129.          end;
  1130.       end
  1131.       else                               { 8 bit }
  1132.       begin
  1133.          Len := Len and $FFFE;
  1134.          pB := PByte(Buf);
  1135.          if (Channel and CH_RIGHT = CH_RIGHT) then inc(pB);
  1136.          while (Len > 0) do
  1137.          begin
  1138.             DLinePos := (DLinePos+1) and mask;
  1139.             DLine^[DLinePos] := pB^;
  1140.             Position := (Position + 1) and mask;
  1141.             if not Started then pB^ := DLine^[Position]
  1142.             else if (Position = 0) then Started := False;
  1143.             inc(pB,2);
  1144.             dec(Len,2*sizeOf(Byte));
  1145.          end;
  1146.       end;
  1147.    end;
  1148. end;
  1149. {$ENDIF}
  1150. {========================================================================}
  1151. { -- PhaseShift --                                                       }
  1152. {                                                                        }
  1153. {    Digital version of the popular '70s effect.  This one               }
  1154. {    does 4 stages just like old MXR Phase 90 stompbox.                  }
  1155. {========================================================================}
  1156. function InitPhaseShift(pwfx: PWaveFormatEx): PPhaseShift;
  1157. begin
  1158.    Result := GlobalAllocMem(SizeOf(TPhaseShift));
  1159.    if (Result <> nil) then
  1160.    begin
  1161.       with Result^ do
  1162.       begin
  1163.          DataType  := GetDataType(pwfx);
  1164.          SampleRate:= pwfx^.nSamplesPerSec;
  1165.          DryMix    := 50 * 256 div 100;
  1166.          WetMix    := 50 * 256 div 100;
  1167.       end;
  1168.    end;
  1169. end;
  1170. {========================================================================}
  1171. procedure DonePhaseShift(var pps: PPhaseShift);
  1172. begin
  1173.    if (pps <> nil) then
  1174.    begin
  1175.       GlobalFreeMem(Pointer(pps));
  1176.    end;
  1177. end;
  1178. {========================================================================}
  1179. procedure SetPhaseShift(pps: PPhaseShift; iDry,iWet,iFeedBack: Longint;
  1180.                         iSweep,iDepth,iRate: Float);
  1181. var
  1182.    Range: Float;
  1183. begin
  1184.    if (pps <> nil) then
  1185.    begin
  1186.       with pps^ do
  1187.       begin
  1188.          FeedBack:= iFeedBack * 256 div 100;
  1189.          DryMix  := iDry * 256 div 100;
  1190.          WetMix  := iWet * 256 div 100;
  1191.          Sweep   := iSweep;
  1192.          Depth   := iDepth;
  1193.          { calc params for sweeping filters }
  1194.          Range := pow(2.0, iDepth);
  1195.          Max_wp := (M_PI * iSweep * Range) / SampleRate;
  1196.          Min_wp := (M_PI * iSweep) / SampleRate;
  1197.          wp := Min_wp;
  1198.          Rate := pow(Range, iRate / (SampleRate / 2));
  1199.          SweepFact := Rate;
  1200.          { reset some things }
  1201.          inL1  := 0;
  1202.          inL2  := 0;
  1203.          inL3  := 0;
  1204.          inL4  := 0;
  1205.          outL1 := 0;
  1206.          outL2 := 0;
  1207.          outL3 := 0;
  1208.          outL4 := 0;
  1209.       end;
  1210.    end;
  1211. end;
  1212. {========================================================================}
  1213. function DoPhaseShift(pps: PPhaseShift; Buf: PChar; Len: Longint): Boolean;
  1214. var
  1215.    pW: PSmallInt;
  1216.    pB: PByte;
  1217.    coef: Longint;
  1218.    inval,outval: Longint;
  1219. begin
  1220.    Result := False;
  1221.    if (pps <> nil) then
  1222.    with pps^ do
  1223.    begin
  1224.       if (DataType and DT_STEREO = DT_STEREO) then  { stereo }
  1225.       begin
  1226.          if (DataType and DT_16BIT = DT_16BIT) then { 16-bit }
  1227.          begin
  1228.             pW := PSmallInt(Buf);
  1229.             while Len > 0 do
  1230.             begin
  1231.                { calc coef for current freq }
  1232.                coef := Trunc(8192*(1.0- wp)/(1.0 + wp));
  1233.                inval := pW^ + sar(outL4 * Feedback,8);
  1234.                { do 1st filter }
  1235.                outL1 := sar(coef*(outL1 + inval),13) - inL1;
  1236.                inL1 := inval;
  1237.                { do 2nd filter }
  1238.                outL2 := sar(coef*(outL2 + outL1),13) - inL2;
  1239.                inL2 := outL1;
  1240.                { do 3rd filter }
  1241.                outL3 := sar(coef*(outL3 + outL2),13) - inL3;
  1242.                inL3 := outL2;
  1243.                { do 4th filter }
  1244.                outL4 := sar(coef*(outL4 + outL3),13) - inL4;
  1245.                inL4 := outL3;
  1246.                { develop final output mix }
  1247.                outval := sar(outL4*WetMix,8);
  1248.                outval := outval+ sar(inval*DryMix,8);
  1249.                { clip output if necessary }
  1250.                if (outval > 32767) then
  1251.                begin
  1252.                   pW^ := 32767;
  1253.                   Result := True;
  1254.                end
  1255.                else if (outval < -32768) then
  1256.                begin
  1257.                   pW^ := -32768;
  1258.                   Result := True;
  1259.                end
  1260.                else pW^ := outval;
  1261.                inc(pW);
  1262.                inval := pW^+ sar(outR4 * Feedback,8);
  1263.                { do 1st filter }
  1264.                outR1 := sar(coef*(outR1 + inval),13) - inR1;
  1265.                inR1 := inval;
  1266.                { do 2nd filter }
  1267.                outR2 := sar(coef*(outR2 + outR1),13) - inR2;
  1268.                inR2 := outR1;
  1269.                { do 3rd filter }
  1270.                outR3 := sar(coef*(outR3 + outR2),13) - inR3;
  1271.                inR3 := outR2;
  1272.                { do 4th filter }
  1273.                outR4 := sar(coef*(outR4 + outR3),13) - inR4;
  1274.                inR4 := outR3;
  1275.                { develop final output mix }
  1276.                outval := sar(outR4*WetMix,8) + sar(inval*DryMix,8);
  1277.                { clip output if necessary }
  1278.                if (outval > 32767) then
  1279.                begin
  1280.                   pW^ := 32767;
  1281.                   Result := True;
  1282.                end
  1283.                else if (outval < -32768) then
  1284.                begin
  1285.                   pW^ := -32768;
  1286.                   Result := True;
  1287.                end
  1288.                else pW^ := outval;
  1289.                inc(pW);
  1290.                wp := wp * SweepFact;         { adjust freq of filters }
  1291.                if (wp > Max_wp) then         { max?                   }
  1292.                   SweepFact := 1.0/Rate      { sweep back down        }
  1293.                else if (wp < Min_wp) then    { min?                   }
  1294.                   SweepFact := Rate;         { sweep back up          }
  1295.                dec(Len,2*sizeOf(SmallInt));
  1296.             end;
  1297.          end
  1298.          else
  1299.          begin
  1300.             pB := PByte(Buf);
  1301.             while Len > 0 do
  1302.             begin
  1303.                { calc coef for current freq }
  1304.                coef := Trunc(8192*(1.0 - wp)/(1.0 + wp));
  1305.                inval := (pB^-128)shl 8 + sar(outL4 * Feedback,8);
  1306.                { do 1st filter }
  1307.                outL1 := sar(coef*(outL1 + inval),13) - inL1;
  1308.                inL1 := inval;
  1309.                { do 2nd filter }
  1310.                outL2 := sar(coef*(outL2 + outL1),13) - inL2;
  1311.                inL2 := outL1;
  1312.                { do 3rd filter }
  1313.                outL3 := sar(coef*(outL3 + outL2),13) - inL3;
  1314.                inL3 := outL2;
  1315.                { do 4th filter }
  1316.                outL4 := sar(coef*(outL4 + outL3),13) - inL4;
  1317.                inL4 := outL3;
  1318.                { develop final output mix }
  1319.                outval := sar(outL4*WetMix,8) + sar(inval*DryMix,8);
  1320.                { clip output if necessary }
  1321.                if (outval > 32767) then
  1322.                begin
  1323.                   pW^ := 32767;
  1324.                   Result := True;
  1325.                end
  1326.                else if (outval < -32768) then
  1327.                begin
  1328.                   pW^ := -32768;
  1329.                   Result := True;
  1330.                end
  1331.                else pW^ := outval;
  1332.                pB^ := (outval shr 8)+128;
  1333.                inc(pB);
  1334.                inval := (pB^-128)shl 8 + sar(outR4 * Feedback,8);
  1335.                { do 1st filter }
  1336.                outR1 := sar(coef*(outR1 + inval),13) - inR1;
  1337.                inR1 := inval;
  1338.                { do 2nd filter }
  1339.                outR2 := sar(coef*(outR2 + outR1),13) - inR2;
  1340.                inR2 := outR1;
  1341.                { do 3rd filter }
  1342.                outR3 := sar(coef*(outR3 + outR2),13) - inR3;
  1343.                inR3 := outR2;
  1344.                { do 4th filter }
  1345.                outR4 := sar(coef*(outR4 + outR3),13) - inR4;
  1346.                inR4 := outR3;
  1347.                { develop final output mix }
  1348.                outval := sar(outR4*WetMix,8) + sar(inval*DryMix,8);
  1349.                { clip output if necessary }
  1350.                if (outval > 32767) then
  1351.                begin
  1352.                   pW^ := 32767;
  1353.                   Result := True;
  1354.                end
  1355.                else if (outval < -32768) then
  1356.                begin
  1357.                   pW^ := -32768;
  1358.                   Result := True;
  1359.                end
  1360.                else pW^ := outval;
  1361.                pB^ := (outval shr 8)+128;
  1362.                inc(pB);
  1363.                wp := wp * SweepFact;         { adjust freq of filters }
  1364.                if (wp > Max_wp) then         { max?                   }
  1365.                   SweepFact := 1.0/Rate      { sweep back down        }
  1366.                else if (wp < Min_wp) then    { min?                   }
  1367.                   SweepFact := Rate;         { sweep back up          }
  1368.                dec(Len,2*sizeOf(Byte));
  1369.             end;
  1370.          end;
  1371.       end
  1372.       else                                          { mono }
  1373.       begin
  1374.          if (DataType and DT_16BIT = DT_16BIT) then { 16-bit }
  1375.          begin
  1376.             pW := PSmallInt(Buf);
  1377.             while Len > 0 do
  1378.             begin
  1379.                { calc coef for current freq }
  1380.                coef := Trunc(8192*(1.0 - wp)/(1.0 + wp));
  1381.                inval := pW^ + sar(outL4 * Feedback,8);
  1382.                { do 1st filter }
  1383.                outL1 := sar(coef*(outL1 + inval),13) - inL1;
  1384.                inL1 := inval;
  1385.                { do 2nd filter }
  1386.                outL2 := sar(coef*(outL2 + outL1),13) - inL2;
  1387.                inL2 := outL1;
  1388.                { do 3rd filter }
  1389.                outL3 := sar(coef*(outL3 + outL2),13) - inL3;
  1390.                inL3 := outL2;
  1391.                { do 4th filter }
  1392.                outL4 := sar(coef*(outL4 + outL3),13) - inL4;
  1393.                inL4 := outL3;
  1394.                { develop final output mix }
  1395.                outval := sar(outL4*WetMix,8) + sar(inval*DryMix,8);
  1396.                { clip output if necessary }
  1397.                if (outval > 32767) then
  1398.                begin
  1399.                   pW^ := 32767;
  1400.                   Result := True;
  1401.                end
  1402.                else if (outval < -32768) then
  1403.                begin
  1404.                   pW^ := -32768;
  1405.                   Result := True;
  1406.                end
  1407.                else pW^ := outval;
  1408.                wp := wp * SweepFact;         { adjust freq of filters }
  1409.                if (wp > Max_wp) then         { max?                   }
  1410.                   SweepFact := 1.0/Rate      { sweep back down        }
  1411.                else if (wp < Min_wp) then    { min?                   }
  1412.                   SweepFact := Rate;         { sweep back up          }
  1413.                inc(pW);
  1414.                dec(Len,sizeOf(SmallInt));
  1415.             end;
  1416.          end
  1417.          else
  1418.          begin
  1419.             pB := PByte(Buf);
  1420.             while Len > 0 do
  1421.             begin
  1422.                { calc coef for current freq }
  1423.                coef := Trunc(8192*(1.0 - wp)/(1.0 + wp));
  1424.                inval := (pB^-128)shl 8 + sar(outL4 * Feedback,8);
  1425.                { do 1st filter }
  1426.                outL1 := sar(coef*(outL1 + inval),13) - inL1;
  1427.                inL1 := inval;
  1428.                { do 2nd filter }
  1429.                outL2 := sar(coef*(outL2 + outL1),13) - inL2;
  1430.                inL2 := outL1;
  1431.                { do 3rd filter }
  1432.                outL3 := sar(coef*(outL3 + outL2),13) - inL3;
  1433.                inL3 := outL2;
  1434.                { do 4th filter }
  1435.                outL4 := sar(coef*(outL4 + outL3),13) - inL4;
  1436.                inL4 := outL3;
  1437.                { develop final output mix }
  1438.                outval := sar(outL4*WetMix,8) + sar(inval*DryMix,8);
  1439.                { clip output if necessary }
  1440.                if (outval > 32767) then
  1441.                begin
  1442.                   pW^ := 32767;
  1443.                   Result := True;
  1444.                end
  1445.                else if (outval < -32768) then
  1446.                begin
  1447.                   pW^ := -32768;
  1448.                   Result := True;
  1449.                end
  1450.                else pW^ := outval;
  1451.                pB^ := (outval shr 8)+128;
  1452.                wp := wp * SweepFact;         { adjust freq of filters }
  1453.                if (wp > Max_wp) then         { max?                   }
  1454.                   SweepFact := 1.0/Rate      { sweep back down        }
  1455.                else if (wp < Min_wp) then    { min?                   }
  1456.                   SweepFact := Rate;         { sweep back up          }
  1457.                inc(pB);
  1458.                dec(Len,sizeOf(Byte));
  1459.             end;
  1460.          end;
  1461.       end;
  1462.    end;
  1463. end;
  1464. {========================================================================}
  1465. { -- Flanger --                                                          }
  1466. {========================================================================}
  1467. function InitFlanger(pwfx: PWaveFormatEx; MaxDelay: integer): PFlanger;
  1468. var
  1469.    i: integer;
  1470. begin
  1471.    Result := GlobalAllocMem(SizeOf(TFlanger));
  1472.    if (Result <> nil) then
  1473.    begin
  1474.       {$IFNDEF USEASM}
  1475.       MaxDelay := Min(MaxDelay,500);
  1476.       {$ENDIF}
  1477.       Result^.MaxDelay := MaxDelay;
  1478.       with Result^ do
  1479.       begin
  1480.          DataType    := GetDataType(pwfx);
  1481.          SampleRate  := pwfx^.nSamplesPerSec;
  1482.          Delay       := 0;
  1483.          DLineL      := nil;
  1484.          DLineR      := nil;
  1485.          DLinePos    := 0;
  1486.                                             { Calculate delay line size }
  1487.          DLineSize := SampleRate*MaxDelay div 1000;
  1488.          i := 0;
  1489.          while DLineSize > 2048 do
  1490.          begin
  1491.             DLineSize := DLineSize shr 1;
  1492.             inc(i);
  1493.          end;
  1494.          DLineSize := 2048;
  1495.          while i > 0 do
  1496.          begin
  1497.             DLineSize := DLineSize shl 1;
  1498.             dec(i);
  1499.          end;
  1500.          DLineL := GlobalAllocMem(DLineSize*sizeOf(Smallint));
  1501.          if (DataType and DT_STEREO = DT_STEREO) then
  1502.              DLineR := GlobalAllocMem(DLineSize*sizeof(Smallint));
  1503.          if (DLineL = nil) or
  1504.             ((DLineR = nil) and (DataType and DT_STEREO = DT_STEREO)) then
  1505.          begin
  1506.             DoneFlanger(Result);
  1507.          end;
  1508.       end;
  1509.    end;
  1510. end;
  1511. {========================================================================}
  1512. procedure DoneFlanger(var pfc: PFlanger);
  1513. begin
  1514.    if (pfc <> nil) then
  1515.    begin
  1516.       GlobalFreeMem(Pointer(pfc^.DLineL));
  1517.       GlobalFreeMem(Pointer(pfc^.DLineR));
  1518.       GlobalFreeMem(Pointer(pfc));
  1519.    end;
  1520. end;
  1521. {========================================================================}
  1522. procedure SetFlanger(pfc: PFlanger; iDry,iWet,iFeedBack,
  1523.                      iDelay: Longint; iDepth, iRate: Float);
  1524. begin
  1525.    if (pfc <> nil) then
  1526.    begin
  1527.       with pfc^ do
  1528.       begin
  1529.          FeedBack:= iFeedBack * 256 div 100;
  1530.          DryMix  := iDry * 256 div 100;
  1531.          WetMix  := iWet * 256 div 100;
  1532.          Rate    := iRate;
  1533.          Depth   := iDepth;
  1534.          Step    := Trunc(iRate * 65.536);
  1535.          Delay   := iDelay;
  1536.          if (Delay > MaxDelay) then
  1537.              Delay := MaxDelay;
  1538.          if (DLineSize > 0) then
  1539.          begin
  1540.             FillChar(DLineL^,DLineSize*sizeOf(Smallint),0);        { Clear delay lines }
  1541.             if (DataType and DT_STEREO = DT_STEREO) then
  1542.                FillChar(DLineR^,DLineSize*sizeOf(Smallint),0);
  1543.          end;
  1544.          DLinePos := 0;
  1545.          ep1 := 0;
  1546.          ep2 := 0;
  1547.          { init/calc some stuff }
  1548.          MaxSweep := DLineSize - (SampleRate * Delay div 1000) - 2;
  1549.          MinSweep := Trunc(MaxSweep - Depth * SampleRate / 1000);
  1550.          if (MinSweep < 0) then MinSweep := 0;
  1551.          LongRec(Sweep).Hi := (MinSweep + MaxSweep) div 2;
  1552.          LongRec(Sweep).Lo := 0;
  1553.       end;
  1554.    end;
  1555. end;
  1556. {========================================================================}
  1557. function DoFlanger(pfc: PFlanger; Buf: PChar; Len: Longint): Boolean;
  1558. const
  1559.     ifac = 65536;
  1560. var
  1561.    pW: PSmallInt;
  1562.    pB: PByte;
  1563.    mask: integer;
  1564.    inval,outval: Longint;
  1565. begin
  1566.    Result := False;
  1567.    if (pfc <> nil) then
  1568.    with pfc^ do
  1569.    begin
  1570.       mask := DLineSize-1;
  1571.       if (DataType and DT_STEREO = DT_STEREO) then  { stereo }
  1572.       begin
  1573.          if (DataType and DT_16BIT = DT_16BIT) then { 16-bit }
  1574.          begin
  1575.             pW := PSmallInt(Buf);
  1576.             while (Len > 0) do
  1577.             begin
  1578.                { interpolate from the 2 read values }
  1579.                outval := (DLineL^[ep1]*LongRec(Sweep).Lo+
  1580.                           DLineL^[ep2]*(ifac-LongRec(Sweep).Lo))div ifac;
  1581.                { store finished input plus feedback }
  1582.                inval := pW^ + sar(outval * Feedback,8);
  1583.                if (inval > 32767) then
  1584.                begin
  1585.                   inval  := 32767;
  1586.                   Result := True;
  1587.                end
  1588.                else if (inval < -32768) then
  1589.                begin
  1590.                   inval  := -32768;
  1591.                   Result := True;
  1592.                end;
  1593.                DLineL^[DLinePos] := inval;
  1594.                { develop final output mix }
  1595.                outval := sar(outval*WetMix,8) + sar(inval*DryMix,8);
  1596.                if (outval > 32767) then
  1597.                begin
  1598.                   outval := 32767;
  1599.                   Result := True;
  1600.                end
  1601.                else if (outval < -32768) then
  1602.                begin
  1603.                   outval := -32768;
  1604.                   Result := True;
  1605.                end;
  1606.                pW^ := outval;
  1607.                inc(pW);
  1608.                { right channel }
  1609.                { interpolate from the 2 read values }
  1610.                outval := (DLineR^[ep1]*LongRec(Sweep).Lo+
  1611.                           DLineR^[ep2]*(ifac-LongRec(Sweep).Lo))div ifac;
  1612.                { store finished input plus feedback }
  1613.                inval := pW^ + sar(outval * Feedback,8);
  1614.                if (inval > 32767) then
  1615.                begin
  1616.                   inval  := 32767;
  1617.                   Result := True;
  1618.                end
  1619.                else if (inval < -32767) then
  1620.                begin
  1621.                   inval  := -32767;
  1622.                   Result := True;
  1623.                end;
  1624.                DLineR^[DLinePos] := inval;
  1625.                { develop final output mix }
  1626.                outval := sar(outval*WetMix,8) + sar(inval*DryMix,8);
  1627.                if (outval > 32767) then
  1628.                begin
  1629.                   outval := 32767;
  1630.                   Result := True;
  1631.                end
  1632.                else if (outval < -32767) then
  1633.                begin
  1634.                   outval := -32767;
  1635.                   Result := True;
  1636.                end;
  1637.                pW^ := outval;
  1638.                inc(pW);
  1639.                { update ptrs }
  1640.                DLinePos := (DLinePos + 1) and mask;
  1641.                sweep := sweep + step;
  1642.                ep1 := (DLinePos + LongRec(Sweep).Hi) and mask;
  1643.                ep2 := (ep1 - 1) and mask;
  1644.                { check for sweep reversal }
  1645.                if (LongRec(Sweep).Hi > MaxSweep) or   { see if we hit top of sweep   }
  1646.                   (LongRec(Sweep).Hi < MinSweep) then { or if we hit bottom of sweep }
  1647.                   Step := -Step;                      { reverse                      }
  1648.                dec(Len,2*sizeOf(SmallInt));
  1649.             end;
  1650.          end
  1651.          else                                       { 8 bit }
  1652.          begin
  1653.             pB := PByte(Buf);
  1654.             while (Len > 0) do
  1655.             begin
  1656.                { left channel }
  1657.                { interpolate from the 2 read values }
  1658.                outval := (DLineL^[ep1]*LongRec(Sweep).Lo+
  1659.                           DLineL^[ep2]*(ifac-LongRec(Sweep).Lo))div ifac;
  1660.                { store finished input plus feedback }
  1661.                inval := (pB^-128)shl 8 + sar(outval * Feedback,8);
  1662.                if (inval > 32767) then
  1663.                begin
  1664.                   inval  := 32767;
  1665.                   Result := True;
  1666.                end
  1667.                else if (inval < -32767) then
  1668.                begin
  1669.                   inval  := -32767;
  1670.                   Result := True;
  1671.                end;
  1672.                DLineL^[DLinePos] := inval;
  1673.                { develop final output mix }
  1674.                outval := sar(outval*WetMix,8) + sar(inval*DryMix,8);
  1675.                if (outval > 32767) then
  1676.                begin
  1677.                   outval := 32767;
  1678.                   Result := True;
  1679.                end
  1680.                else if (outval < -32768) then
  1681.                begin
  1682.                   outval := -32768;
  1683.                   Result := True;
  1684.                end;
  1685.                pB^ := (outval shr 8)+128;
  1686.                inc(pB);
  1687.                { right channel }
  1688.                { interpolate from the 2 read values }
  1689.                outval := (DLineR^[ep1]*LongRec(Sweep).Lo+
  1690.                           DLineR^[ep2]*(ifac-LongRec(Sweep).Lo))div ifac;
  1691.                { store finished input plus feedback }
  1692.                inval := (pB^-128) shl 8 + sar(outval * Feedback,8);
  1693.                if (inval > 32767) then
  1694.                begin
  1695.                   inval  := 32767;
  1696.                   Result := True;
  1697.                end
  1698.                else if (inval < -32767) then
  1699.                begin
  1700.                   inval  := -32767;
  1701.                   Result := True;
  1702.                end;
  1703.                DLineR^[DLinePos] := inval;
  1704.                { develop final output mix }
  1705.                outval := sar(outval*WetMix,8) + sar(inval*DryMix,8);
  1706.                if (outval > 32767) then
  1707.                begin
  1708.                   outval := 32767;
  1709.                   Result := True;
  1710.                end
  1711.                else if (outval < -32768) then
  1712.                begin
  1713.                   outval := -32768;
  1714.                   Result := True;
  1715.                end;
  1716.                pB^ := (outval shr 8)+128;
  1717.                inc(pB);
  1718.                { update ptrs }
  1719.                DLinePos := (DLinePos + 1) and mask;
  1720.                sweep := sweep + step;
  1721.                ep1 := (DLinePos + LongRec(Sweep).Hi) and mask;
  1722.                ep2 := (ep1 - 1) and mask;
  1723.                { check for sweep reversal }
  1724.                if (LongRec(Sweep).Hi > MaxSweep) or   { see if we hit top of sweep   }
  1725.                   (LongRec(Sweep).Hi < MinSweep) then { or if we hit bottom of sweep }
  1726.                   Step := -Step;                      { reverse                      }
  1727.                dec(Len,2*sizeOf(Byte));
  1728.             end;
  1729.          end;
  1730.       end
  1731.       else                                          { mono }
  1732.       begin
  1733.          if (DataType and DT_16BIT = DT_16BIT) then { 16-bit }
  1734.          begin
  1735.             pW := PSmallInt(Buf);
  1736.             while (Len > 0) do
  1737.             begin
  1738.                { interpolate from the 2 read values }
  1739.                outval := (DLineL^[ep1]*LongRec(Sweep).Lo+
  1740.                           DLineL^[ep2]*(ifac-LongRec(Sweep).Lo))div ifac;
  1741.                { store finished input plus feedback }
  1742.                inval := pW^ + sar(outval*Feedback,8);
  1743.                if (inval > 32767) then
  1744.                begin
  1745.                   inval  := 32767;
  1746.                   Result := True;
  1747.                end
  1748.                else if (inval < -32767) then
  1749.                begin
  1750.                   inval  := -32767;
  1751.                   Result := True;
  1752.                end;
  1753.                DLineL^[DLinePos] := inval;
  1754.                { develop final output mix }
  1755.                outval := sar(outval*WetMix,8) + sar(inval*DryMix,8);
  1756.                if (outval > 32767) then
  1757.                begin
  1758.                   outval := 32767;
  1759.                   Result := True;
  1760.                end
  1761.                else if (outval < -32768) then
  1762.                begin
  1763.                   outval := -32768;
  1764.                   Result := True;
  1765.                end;
  1766.                pW^ := outval;
  1767.                inc(pW);
  1768.                { update ptrs }
  1769.                DLinePos := (DLinePos + 1) and mask;
  1770.                sweep := sweep + step;
  1771.                ep1 := (DLinePos + LongRec(Sweep).Hi) and mask;
  1772.                ep2 := (ep1 - 1) and mask;
  1773.                { check for sweep reversal }
  1774.                if (LongRec(Sweep).Hi > MaxSweep) or   { see if we hit top of sweep   }
  1775.                   (LongRec(Sweep).Hi < MinSweep) then { or if we hit bottom of sweep }
  1776.                   Step := -Step;                      { reverse                      }
  1777.                dec(Len,sizeOf(SmallInt));
  1778.             end;
  1779.          end
  1780.          else
  1781.          begin                                      { 8 Bit }
  1782.             pB := PByte(Buf);
  1783.             while (Len > 0) do
  1784.             begin
  1785.                { interpolate from the 2 read values }
  1786.                outval := (DLineL^[ep1]*LongRec(Sweep).Lo+
  1787.                           DLineL^[ep2]*(ifac-LongRec(Sweep).Lo))div ifac;
  1788.                { store finished input plus feedback }
  1789.                inval := (pB^-128)shl 8 + sar(outval*Feedback,8);
  1790.                if (inval > 32767) then
  1791.                begin
  1792.                   inval  := 32767;
  1793.                   Result := True;
  1794.                end
  1795.                else if (inval < -32767) then
  1796.                begin
  1797.                   inval  := -32767;
  1798.                   Result := True;
  1799.                end;
  1800.                DLineL^[DLinePos] := inval;
  1801.                { develop final output mix }
  1802.                outval := sar(outval*WetMix,8) + sar(inval*DryMix,8);
  1803.                if (outval > 32767) then
  1804.                begin
  1805.                   outval := 32767;
  1806.                   Result := True;
  1807.                end
  1808.                else if (outval < -32768) then
  1809.                begin
  1810.                   outval := -32768;
  1811.                   Result := True;
  1812.                end;
  1813.                pB^ := (outval shr 8)+128;
  1814.                inc(pB);
  1815.                { update ptrs }
  1816.                DLinePos := (DLinePos + 1) and mask;
  1817.                sweep := sweep + step;
  1818.                ep1 := (DLinePos + LongRec(Sweep).Hi) and mask;
  1819.                ep2 := (ep1 - 1) and mask;
  1820.                { check for sweep reversal }
  1821.                if (LongRec(Sweep).Hi > MaxSweep) or   { see if we hit top of sweep   }
  1822.                   (LongRec(Sweep).Hi < MinSweep) then { or if we hit bottom of sweep }
  1823.                   Step := -Step;                      { reverse                      }
  1824.                dec(Len,sizeOf(Byte));
  1825.             end;
  1826.          end;
  1827.       end;
  1828.    end;
  1829. end;
  1830. {========================================================================}
  1831. { -- PitchChange --                                                      }
  1832. {========================================================================}
  1833. function InitPitchChange(pwfx: PWaveFormatEx; MaxDelay: integer): PPitchChange;
  1834. var
  1835.    i: integer;
  1836. begin
  1837.    Result := GlobalAllocMem(SizeOf(TPitchChange));
  1838.    if (Result <> nil) then
  1839.    begin
  1840.       {$IFNDEF USEASM}
  1841.       MaxDelay := Min(MaxDelay,500);
  1842.       {$ENDIF}
  1843.       Result^.MaxDelay := MaxDelay;
  1844.       with Result^ do
  1845.       begin
  1846.          DataType    := GetDataType(pwfx);
  1847.          SampleRate  := pwfx^.nSamplesPerSec;
  1848.          Delay       := 0;
  1849.          DLineL      := nil;
  1850.          DLineR      := nil;
  1851.                                             { Calculate delay line size }
  1852.          DLineSize := MulDiv32(SampleRate,MaxDelay,1000);
  1853.          i := 0;
  1854.          while DLineSize > 2048 do
  1855.          begin
  1856.             DLineSize := DLineSize shr 1;
  1857.             inc(i);
  1858.          end;
  1859.          DLineSize := 2048;
  1860.          while i > 0 do
  1861.          begin
  1862.             DLineSize := DLineSize shl 1;
  1863.             dec(i);
  1864.          end;
  1865.          DLineSize := 4096;
  1866.          DLineL := GlobalAllocMem(sizeOf(Longint)*DLineSize);
  1867.          if (DataType and DT_STEREO = DT_STEREO) then
  1868.              DLineR := GlobalAllocMem(sizeOf(Longint)*DLineSize);
  1869.          if (DLineL = nil) or
  1870.             ((DLineR = nil) and (DataType and DT_STEREO = DT_STEREO)) then
  1871.          begin
  1872.             DonePitchChange(Result);
  1873.          end;
  1874.       end;
  1875.    end;
  1876. end;
  1877. {========================================================================}
  1878. procedure DonePitchChange(var ppc: PPitchChange);
  1879. begin
  1880.    if (ppc <> nil) then
  1881.    begin
  1882.       GlobalFreeMem(Pointer(ppc^.DLineL));
  1883.       GlobalFreeMem(Pointer(ppc^.DLineR));
  1884.       GlobalFreeMem(Pointer(ppc));
  1885.    end;
  1886. end;
  1887. {========================================================================}
  1888. procedure SetPitchChange(ppc: PPitchChange; iDry,iWet,iFeedBack,
  1889.                          iDelay,iDepth: Longint; iRate: Float);
  1890. var
  1891.    i: integer;
  1892. begin
  1893.    if (ppc <> nil) then
  1894.    begin
  1895.       with ppc^ do
  1896.       begin
  1897.          FeedBack:= iFeedBack * 256 div 100;
  1898.          DryMix  := iDry * 256 div 100;
  1899.          WetMix  := iWet * 256 div 100;
  1900.          Rate    := iRate;
  1901.          Depth   := iDepth;        //???????
  1902.          Step    := Trunc(iRate * 65535.0);
  1903.          Delay   := Min(iDelay,MaxDelay);   //????
  1904.          if (DLineSize > 0) then
  1905.          begin
  1906.             FillChar(DLineL^,sizeOf(Longint)*DLineSize,0);{ Clear delay lines }
  1907.             if (DataType and DT_STEREO = DT_STEREO) then
  1908.                FillChar(DLineR^,sizeOf(Longint)*DLineSize,0);
  1909.          end;
  1910.          // fetch params
  1911.          SweepUp := True {Rate > 0};
  1912.          XFade := Min(12 * SampleRate div 1000,MAX_XTAB);
  1913.          // init/calc some stuff
  1914.          MaxSweep := DLineSize - 2 - MulDiv32(SampleRate,Delay,1000);
  1915.          MinSweep := Max(MaxSweep - MulDiv32(SampleRate,Depth,1000),0);
  1916.          Active   := Trunc(MaxSweep - MinSweep - (XFade * Rate) - 2);
  1917.          { build the crossfade lookup tables }
  1918.          for i := 0 to XFade-1 do
  1919.          begin
  1920.             Fade_In[i] := cos(i * M2_PI / XFade);
  1921.             Fade_Out[i]:= sin(i * M2_PI / XFade);
  1922.          end;
  1923.          // init store and read ptrs to known value, chanA active 1st
  1924.          fp := 0;
  1925.          ep3 := 0;
  1926.          ep4 := 0;
  1927.          XFadeCnt := 0;
  1928.          Sweep := 0;
  1929.          if SweepUp then
  1930.          begin
  1931.             ep1 := MinSweep;
  1932.             ep2 := MinSweep;
  1933.          end
  1934.          else
  1935.          begin
  1936.             ep1 := MaxSweep;
  1937.             ep2 := MaxSweep;
  1938.          end;
  1939.          ActiveCnt := Active;
  1940.          BlendA    := 1.0;
  1941.          BlendB    := 0.0;
  1942.          FadeA     := @Fade_Out;
  1943.          FadeB     := @Fade_In;
  1944.          ChanA     := True;
  1945.       end;
  1946.    end;
  1947. end;
  1948. {========================================================================}
  1949. procedure DoPitchChange(ppc: PPitchChange; Buffer: PChar; Len: Longint);
  1950. Label Next;
  1951. const
  1952.     ifac = 65536.0;
  1953. var
  1954.    pW: PSmallInt;
  1955.    mask: integer;
  1956.    Inval,Outval: Longint;
  1957.    comp: Float;
  1958.    // macros for pitch_change delay index manipulation
  1959.    procedure inc_index(var x: integer);
  1960.    begin
  1961.       x := (x + 1) and mask;
  1962.    end;
  1963.    procedure inc_indexes(var x1,x2: integer);
  1964.    begin
  1965.       x2 := x1;
  1966.       inc_index(x1);
  1967.    end;
  1968. begin
  1969.    if (ppc <> nil) then
  1970.    with ppc^ do
  1971.    begin
  1972.       mask := DLineSize-1;
  1973.                                                 { mono }
  1974.       if (DataType and DT_16BIT = DT_16BIT) then { 16-bit }
  1975.       begin
  1976.          pW := PSmallInt(Buffer);
  1977.          while (Len > 0) do
  1978.          begin
  1979.             // messy expression to interpolate from both pairs of read ptrs
  1980.             comp := ifac - Sweep;
  1981.             Outval := Trunc(((DLineL^[ep1] * LongRec(Sweep).Lo + DLineL^[ep2] * comp) * BlendA +
  1982.                              (DLineL^[ep3] * LongRec(Sweep).Lo + DLineL^[ep4] * comp) * BlendB)
  1983.                               / ifac);
  1984.             // store finished input plus feedback
  1985.             inval := pW^ + sar(Outval*Feedback,8);
  1986.             DLineL^[fp] := inval;
  1987.             { develop final output mix }
  1988.             Outval := sar(Outval*WetMix,8) + sar(Inval*DryMix,8);
  1989.             if (Outval > 32767) then pW^ := 32767
  1990.             else if (Outval < -32767) then pW^ := -32767
  1991.             else pW^ := Outval;
  1992.             // see if crossfade active
  1993.             if (XFadeCnt > 0) then
  1994.             begin
  1995.                dec(XFadeCnt);
  1996.                BlendA := FadeA[XFadeCnt];
  1997.                BlendB := FadeB[XFadeCnt];
  1998.             end;
  1999.             // update store ptr
  2000.             inc_index(fp);
  2001.             // see which direction
  2002.             if SweepUp then
  2003.             begin
  2004.                // update sweep
  2005.                Sweep := Sweep + Word(Step);
  2006.                // always inc at least once
  2007.                inc_indexes(ep1,ep2);
  2008.                inc_indexes(ep3,ep4);
  2009.                // if sweep didn't overflow, we're done
  2010.                if (LongRec(sweep).Hi = 0) then goto next;
  2011.                // sweep overflowed, inc again
  2012.                inc_indexes(ep1,ep2);
  2013.                inc_indexes(ep3,ep4);
  2014.                LongRec(Sweep).Hi := 0;
  2015.                // see if it's time to switch over to other delay channel
  2016.                dec(ActiveCnt);
  2017.                if (ActiveCnt = 0) then
  2018.                begin
  2019.                   XFadeCnt := XFade;      // initiate crossfade
  2020.                   ActiveCnt := Active;    // start counter on new channel
  2021.                   if (ChanA) then         // A has been active, go to B
  2022.                   begin
  2023.                      ChanA := False;
  2024.                      ep3   := (fp + MinSweep) and mask;
  2025.                      FadeA := @Fade_Out;
  2026.                      FadeB := @Fade_In;
  2027.                   end
  2028.                   else
  2029.                   begin
  2030.                      chanA := True;
  2031.                      ep1   := (fp + MinSweep) and mask;
  2032.                      FadeB := @Fade_Out;
  2033.                      FadeA := @Fade_In;
  2034.                   end;
  2035.                end;
  2036.             end
  2037.             else  // do downward sweep
  2038.             begin
  2039.                Sweep := Sweep + Step;   // update sweep
  2040.                // if sweep didn't overflow, inc ptrs, that's all
  2041.                if (LongRec(Sweep).Hi = 0) then
  2042.                begin
  2043.                   inc_indexes(ep1,ep2);
  2044.                   inc_indexes(ep3,ep4);
  2045.                   goto next;
  2046.                end;
  2047.                // sweep overflowed, check on stuff but skip ptr inc
  2048.                LongRec(Sweep).Hi := 0;
  2049.                // see if it's time to switch over to other delay channel
  2050.                dec(ActiveCnt);
  2051.                if (ActiveCnt = 0) then
  2052.                begin
  2053.                   XFadeCnt  := XFade;
  2054.                   ActiveCnt := Active;
  2055.                   if ChanA then       // A has been active, go to B */
  2056.                   begin
  2057.                      ChanA := False;
  2058.                      ep3   := (fp + MaxSweep) and mask;
  2059.                      FadeA := @Fade_Out;
  2060.                      FadeB := @Fade_In;
  2061.                   end
  2062.                   else
  2063.                   begin
  2064.                      ChanA := True;
  2065.                      ep1   := (fp + MaxSweep) and mask;
  2066.                      FadeB := @Fade_Out;
  2067.                      FadeA := @Fade_In;
  2068.                   end;
  2069.                end;
  2070.             end;
  2071. Next:
  2072.             inc(pW);
  2073.             dec(Len,sizeOf(SmallInt));
  2074.          end;
  2075.       end;
  2076.    end;
  2077. end;
  2078. end.
  2079. function ReadWaveBuffer( HWND hwnd /*void*/ )
  2080. { //int far *temp;
  2081.   static start=0,
  2082.   shag=-1,
  2083.   ff_shift=10;
  2084.   extern f_shift,Flanger,Equalizer,Reverb;
  2085.   static Flang_buf[260];}
  2086. begin
  2087.   if (start = 0) then
  2088.   begin
  2089.       //init_imp(256,8,2,50);
  2090.       start := 1;
  2091.   end;
  2092.   // if we haven't encountered the end of the wave yet,
  2093.   // read another buffer in...
  2094.   if( dwBytedatasize < dwTotalwavesize-45 ) then
  2095.   begin
  2096.      // read wave chunk from the temporary file...
  2097.      //pwavehdr[bufindex]->dwBufferLength = _lread( htmpfile, pwavemem[bufindex], WaveBufSize );
  2098.      pwavehdr[bufindex]^.dwBufferLength := _lread(htmpfile, inp_buf, WaveBufSize);
  2099.      temp :=  pwavemem[bufindex];
  2100.      //---------------- ! FFT filtr -----------------
  2101.      if (Equalizer = 1) then
  2102.      begin
  2103.         fft_filter(256, 8, 40)
  2104.      end
  2105.      else
  2106.      begin
  2107.         for i := 0 to (256*40)-1 do
  2108.         begin
  2109.            inp_buf[i] := inp_buf[i] shr 1;
  2110.         end;
  2111.      end;
  2112.      //if( Reverb == 1 ){ ReverB();}
  2113.      //_fmemcpy(&temp[256*40],inp_buf,256*80 );
  2114.      //f_shift = 400;shag=-1;
  2115.      if (Chorus = 0) then
  2116.      begin
  2117. if (Flanger = 0) then
  2118.         begin
  2119.    for i := 0 to (256*40)-1 do
  2120.            begin
  2121.               temp[i*2]   := inp_buf[i];
  2122.               temp[i*2+1] := inp_buf[i];
  2123.            end;
  2124.         end
  2125.         else
  2126. begin
  2127.            //---------------------- FLANGER ---------------------------
  2128.    for i := 0 to (256*40)-1 do
  2129.            begin
  2130.               if (i mod 90 = 0) then
  2131.               begin
  2132.  ff_shift := ff_shift + shag;
  2133.                  if (ff_shift > 250) then shag := -1;
  2134.                  if (ff_shift < 50) then shag := 1;
  2135.               end;
  2136.               //----------------------------------------------------------
  2137.       if(i < ff_shift) then
  2138.               begin
  2139.  temp[_i*2+1]=temp[_i*2]=((long)((long)flang_buf[1000-ff_shift+_i] +(long)inp_buf[_i])>>1);
  2140.               end
  2141.               else
  2142.               begin
  2143.  temp[_i*2+1]=temp[_i*2]=((long)((long)inp_buf[_i-ff_shift] + (long)inp_buf[_i])>>1);
  2144.               end;
  2145.               //if(_i>=10240-1900){ flang_buf[1900-10240+_i]=inp_buf[_i];}
  2146.            end;
  2147.    _fmemcpy(&flang_buf[0],&inp_buf[10240-1000],1000*2 );
  2148.         end;
  2149.      end
  2150.      else //---- stereo chorus ON ---------------------------
  2151.      begin
  2152.         //---------------------- FLANGER ---------------------------
  2153. if (Flanger = 1) or (Flanger = 2) then
  2154.         begin
  2155.    _fmemcpy(temp,inp_buf,256*80);
  2156.    if (Flanger = 1) then
  2157.            begin
  2158.               for (i := 0 to (256*40)-1 do
  2159.               begin
  2160.  if (i mod 90 = 0) then
  2161.                  begin
  2162.                     ff_shift := ff_shift + shag;
  2163.                     if (ff_shift > 250) then shag := -1;
  2164.                     if (ff_shift < 25) then shag :=1;
  2165.                  end;
  2166.  if (i < ff_shift) then
  2167.                  begin
  2168.                     inp_buf[_i]= ((long)Flang_buf[259-ff_shift+_i]+(long)temp[_i])>>0;
  2169.                  end
  2170.                  else
  2171.  begin
  2172.                     inp_buf[_i]=((long)temp[_i-ff_shift]+(long)temp[_i])>>0; }
  2173.                  end;
  2174.               end;
  2175.            end
  2176.            else
  2177.    begin
  2178.       for i := 0 to (256*40)-1 do
  2179.               begin
  2180.          if (i mod 60 = 0) then
  2181.                  begin
  2182.                     ff_shift := ff_shift + shag;
  2183.                     if (ff_shift > 250) then shag := -1;
  2184.                     if (ff_shift < 50) then shag :=1;
  2185.                  end;
  2186.                  if (i < ff_shift) then
  2187.                  begin
  2188.                     inp_buf[_i]= ((long)Flang_buf[259-ff_shift+_i]+(long)temp[_i])>>0;
  2189.                  end
  2190.                  else
  2191.                  begin
  2192.             inp_buf[_i]=((long)temp[_i-ff_shift]+(long)temp[_i])>>0;
  2193.                  end;
  2194.               end;
  2195.            end;
  2196.            _fmemcpy(&Flang_buf[0],&temp[10240-259],259*2 );
  2197.         end;
  2198. //for(_i=0;_i<256*40;_i++){ temp[_i*2]=temp[_i*2+1]=inp_buf[_i];}
  2199. //------------------------------- CHORUS -------
  2200. for i := 0 to (256*40)-1 do
  2201.         begin
  2202.            temp[i*2+1] := inp_buf[i];
  2203.            if (i < f_shift) then
  2204.            begin
  2205.               temp[i*2] := flang_buf[1000-f_shift+i];
  2206.            end
  2207.            else
  2208.    begin
  2209.               temp[i*2]=inp_buf[i-f_shift]; }
  2210.            end;
  2211.    //for(_i=0;_i<256*40;_i++)
  2212.            {
  2213.      //if(_i>=10240-1900){ flang_buf[1900-10240+_i]=inp_buf[_i];}
  2214.            }
  2215.    _fmemcpy(&flang_buf[0],&inp_buf[10240-1000],1000*2 );
  2216.         end;
  2217.         //if( Reverb == 1 ){ ReverB1(179,127,151); ReverB2(199,107,139);}
  2218. //if( Reverb == 2 ){ ReverB1(757,523,617); ReverB2(787,503,643);}
  2219.         if (Reverb = 1) then
  2220.         begin
  2221.            ReverB1(179, 127,151,111,251);
  2222.            ReverB2(199,107,139,117,257);
  2223.         end;
  2224. if (Reverb = 2) then
  2225.         begin
  2226.            ReverB1(1003,761,523,397,401);
  2227.            ReverB2(997,769,541,393,239);
  2228.         end;
  2229. if (Reverb = 3) then
  2230.         begin
  2231.            ReverB1(2203,1511,1049,787,241);
  2232.            ReverB2(2179,1523,1061,773,251);
  2233.         end;
  2234.         // update total number of bytes read so far...
  2235. dwBytedatasize += (pwavehdr[bufindex]->dwBufferLength);
  2236.         //-!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  2237. pwavehdr[bufindex]->dwBufferLength *=2L;
  2238. }
  2239. else
  2240. {
  2241. //mmtime.u.cb = 0;
  2242. dwBytedatasize  = 0;
  2243. UpdateLength( hwnd, 0, 0 );
  2244. lseek( htmpfile, 44L, SEEK_SET );
  2245. // read wave chunk from the temporary file...
  2246. //pwavehdr[bufindex]->dwBufferLength = _lread( htmpfile, pwavemem[bufindex], WaveBufSize );
  2247. pwavehdr[bufindex]->dwBufferLength = 0;
  2248. // update total number of bytes read so far...
  2249. dwBytedatasize += pwavehdr[bufindex]->dwBufferLength;
  2250.           /*----------- OLD Version ---------------------*/
  2251.                 // otherwise the last buffer has been queued, just let it finish playing...
  2252. //MoreBuffers = OFF; // handled in MM_WOM_DONE in MainWndProc()
  2253. //return 1;
  2254.           /*---------- END Old Version ------------------*/
  2255. }
  2256. return 0;
  2257. }
  2258. end.
  2259. *)
  2260. (*
  2261. -------------------------------------------------------------------------
  2262. 3.4 Distortion
  2263. --------------
  2264. Now its time to get some sound output. Connect an amplifier or speaker  to 
  2265. the speaker/headphone connector of the SGPRO16 card. Select the Distortion 
  2266. option and set the level to 0. The only thing the program does is  reading 
  2267. ADC sample values and feeding them to the DAC, without  altering  them  at 
  2268. all. You should now hear the sound  you  input  to  the  card.  If  it  is 
  2269. distorted there are two possible causes: if the input level is  too  high, 
  2270. adjust your instrument volume, or decrease the input  gain  entry  in  the 
  2271. configuration file. If the output level is too high, adjust  it  with  the 
  2272. volume control on your card, or decrease the DAC attenuation entry in  the 
  2273. configuration file.
  2274. My machine is not fast enough to run this algorithm at 48 kHz. At  48  kHz 
  2275. clicks are audible, because the program is sometimes too late  to  read  a
  2276. sample from the ADC. The highest  sample  rate  that  doesn't  cause  this 
  2277. problem is 32 kHz. If you have a very slow machine, the number of  samples 
  2278. it misses is so large that it causes  the  sound  to  be  distorted  quite
  2279. heavily.
  2280. Setting the distortion level to a  level  higher  than  0  will  create  a 
  2281. distorted sound. I use quite a naive algorithm. For a  certain  distortion 
  2282. level (Level) the value input to the DAC (In) is related to the ADC output 
  2283. (Out) by: 
  2284.                                     (1 - Level/10) 
  2285.                          ( abs(In) ) 
  2286. Out = 32767 * sign(In) * ( ------- )
  2287.                          (  32767  ) 
  2288.  processed_buf[i] = 32767*sign(in)*(abs(in)/32767)^(1-level/10);
  2289.  
  2290. Both In and Out are signed 16-bit integers. The use of this function  also 
  2291. compresses the signal: small volume signals are amplified more than  large 
  2292. ones. 
  2293. *)
  2294. (* Values for reverb
  2295.    { Hall Reverb
  2296.     ------------ }
  2297.     {FeedBack := 30;
  2298.     NumReverbs := 5;
  2299.     Reverb[0].Delay := 100;
  2300.     Reverb[0].Gain := -15;
  2301.     Reverb[1].Delay := 120;
  2302.     Reverb[1].Gain := 30;
  2303.     Reverb[2].Delay := 140;
  2304.     Reverb[2].Gain := -35;
  2305.     Reverb[3].Delay := 175;
  2306.     Reverb[3].Gain := 30;
  2307.     Reverb[4].Delay := 200;
  2308.     Reverb[4].Gain := 20;}
  2309.    { Room Reverb
  2310.     ------------ }
  2311.     {FeedBack := 35;
  2312.     NumReverbs := 4;
  2313.     Reverb[0].Delay := 5;
  2314.     Reverb[0].Gain :=  20;
  2315.     Reverb[1].Delay := 20;
  2316.     Reverb[1].Gain := -30;
  2317.     Reverb[2].Delay := 30;
  2318.     Reverb[2].Gain :=  -20;
  2319.     Reverb[3].Delay := 40;
  2320.     Reverb[3].Gain := 40;}
  2321.    { Hall Reverb Big
  2322.     ---------------- }
  2323.    { FeedBack := 86;
  2324.     NumReverbs := 5;
  2325.     Reverb[0].Delay := 42;
  2326.     Reverb[0].Gain :=  16;
  2327.     Reverb[1].Delay := 79;
  2328.     Reverb[1].Gain := -19;
  2329.     Reverb[2].Delay := 107;
  2330.     Reverb[2].Gain :=  24;
  2331.     Reverb[3].Delay := 157;
  2332.     Reverb[3].Gain := -27;
  2333.     Reverb[4].Delay := 163;
  2334.     Reverb[4].Gain := -28;}
  2335.    { Metallic Reverb
  2336.     ---------------- }
  2337.    { FeedBack := 60;
  2338.     NumReverbs := 4;
  2339.     Reverb[0].Delay := 30;
  2340.     Reverb[0].Gain :=  30;
  2341.     Reverb[1].Delay := 40;
  2342.     Reverb[1].Gain := -25;
  2343.     Reverb[2].Delay := 50;
  2344.     Reverb[2].Gain :=  25;
  2345.     Reverb[3].Delay := 80;
  2346.     Reverb[3].Gain :=  25; }
  2347.    { Air Duct Reverb
  2348.     ----------------- }
  2349.    { FeedBack := 60;
  2350.     NumReverbs := 4;
  2351.     Reverb[0].Delay := 20;
  2352.     Reverb[0].Gain :=  18;
  2353.     Reverb[1].Delay := 40;
  2354.     Reverb[1].Gain := -48;
  2355.     Reverb[2].Delay := 50;
  2356.     Reverb[2].Gain :=  58;
  2357.     Reverb[3].Delay := 90;
  2358.     Reverb[3].Gain :=  13;}
  2359.    { Distance Echo
  2360.     --------------- }
  2361.    { FeedBack := 75;
  2362.     NumReverbs := 2;
  2363.     Reverb[0].Delay := 160;
  2364.     Reverb[0].Gain :=  30;
  2365.     Reverb[1].Delay := 300;
  2366.     Reverb[1].Gain :=  50;}
  2367.    { Bass Bost
  2368.     ----------- }
  2369.    { FeedBack := 0;
  2370.     NumReverbs := 1;
  2371.     Reverb[0].Delay := 0;
  2372.     Reverb[0].Gain := 60;}
  2373.    { Heavy Bass Boost
  2374.     ----------------- }
  2375.    { FeedBack := -10;
  2376.     NumReverbs := 1;
  2377.     Reverb[0].Delay := 0;
  2378.     Reverb[0].Gain := 150;}
  2379.    { Cathedral 1
  2380.     ------------ }
  2381.     {FeedBack := -47;
  2382.     NumReverbs := 5;
  2383.     Reverb[0].Delay := 100;
  2384.     Reverb[0].Gain := 16;
  2385.     Reverb[1].Delay := 150;
  2386.     Reverb[1].Gain := -20;
  2387.     Reverb[2].Delay := 200;
  2388.     Reverb[2].Gain := 36;
  2389.     Reverb[3].Delay := 250;
  2390.     Reverb[3].Gain := -20;
  2391.     Reverb[4].Delay := 300;
  2392.     Reverb[4].Gain := -24; }
  2393.    { Cathedral 2
  2394.     ------------ }
  2395.     {FeedBack := 24;
  2396.     NumReverbs := 8;
  2397.     Reverb[0].Delay := 100;
  2398.     Reverb[0].Gain := 17;
  2399.     Reverb[1].Delay := 150;
  2400.     Reverb[1].Gain := -24;
  2401.     Reverb[2].Delay := 200;
  2402.     Reverb[2].Gain := 27;
  2403.     Reverb[3].Delay := 250;
  2404.     Reverb[3].Gain := -20;
  2405.     Reverb[4].Delay := 300;
  2406.     Reverb[4].Gain := -24;
  2407.     Reverb[5].Delay := 400;
  2408.     Reverb[5].Gain := 16;
  2409.     Reverb[6].Delay := 500;
  2410.     Reverb[6].Gain := -13;
  2411.     Reverb[7].Delay := 700;
  2412.     Reverb[7].Gain := 6;}
  2413.    { Very Big Hall
  2414.     -------------- }
  2415.    { FeedBack := 40;
  2416.     NumReverbs := 5;
  2417.     Reverb[0].Delay := 20;
  2418.     Reverb[0].Gain := 42;
  2419.     Reverb[1].Delay := 20;
  2420.     Reverb[1].Gain := -36;
  2421.     Reverb[2].Delay := 49;
  2422.     Reverb[2].Gain := 31;
  2423.     Reverb[3].Delay := 160;
  2424.     Reverb[3].Gain := 34;
  2425.     Reverb[4].Delay := 980;
  2426.     Reverb[4].Gain := 16;}
  2427.    { Reverb 1
  2428.     --------- }
  2429.    { FeedBack := 13;
  2430.     NumReverbs := 3;
  2431.     Reverb[0].Delay := 50;
  2432.     Reverb[0].Gain := -70;
  2433.     Reverb[1].Delay := 75;
  2434.     Reverb[1].Gain := 31;
  2435.     Reverb[2].Delay := 100;
  2436.     Reverb[2].Gain := 40;}
  2437.    { Reverb 2
  2438.     --------- }
  2439.    { FeedBack := -16;
  2440.     NumReverbs := 5;
  2441.     Reverb[0].Delay := 50;
  2442.     Reverb[0].Gain := -70;
  2443.     Reverb[1].Delay := 75;
  2444.     Reverb[1].Gain := 31;
  2445.     Reverb[2].Delay := 100;
  2446.     Reverb[2].Gain := 40;
  2447.     Reverb[3].Delay := 25;
  2448.     Reverb[3].Gain := 13;
  2449.     Reverb[4].Delay := 90;
  2450.     Reverb[4].Gain := -16;}
  2451.    { Hagel
  2452.     ------ }
  2453.     {FeedBack := 31;
  2454.     NumReverbs := 8;
  2455.     Reverb[0].Delay := 50;
  2456.     Reverb[0].Gain := 20;
  2457.     Reverb[1].Delay := 70;
  2458.     Reverb[1].Gain := -8;
  2459.     Reverb[2].Delay := 100;
  2460.     Reverb[2].Gain := 14;
  2461.     Reverb[3].Delay := 120;
  2462.     Reverb[3].Gain := -6;
  2463.     Reverb[4].Delay := 140;
  2464.     Reverb[4].Gain := 22;
  2465.     Reverb[5].Delay := 150;
  2466.     Reverb[5].Gain := -5;
  2467.     Reverb[6].Delay := 160;
  2468.     Reverb[6].Gain := 16;
  2469.     Reverb[7].Delay := 170;
  2470.     Reverb[7].Gain := -2;}
  2471.    { Big Room
  2472.     ---------- }
  2473.    { FeedBack := 16;
  2474.     NumReverbs := 8;
  2475.     Reverb[0].Delay := 40;
  2476.     Reverb[0].Gain := -17;
  2477.     Reverb[1].Delay := 60;
  2478.     Reverb[1].Gain := 8;
  2479.     Reverb[2].Delay := 100;
  2480.     Reverb[2].Gain := 3;
  2481.     Reverb[3].Delay := 120;
  2482.     Reverb[3].Gain := 0;
  2483.     Reverb[4].Delay := 140;
  2484.     Reverb[4].Gain := 33;
  2485.     Reverb[5].Delay := 150;
  2486.     Reverb[5].Gain := 0;
  2487.     Reverb[6].Delay := 160;
  2488.     Reverb[6].Gain := 27;
  2489.     Reverb[7].Delay := 170;
  2490.     Reverb[7].Gain := 31; }
  2491.    { Simple Echo
  2492.     ------------ }
  2493.     {FeedBack := 0;
  2494.     NumReverbs := 1;
  2495.     Reverb[0].Delay := 150;
  2496.     Reverb[0].Gain := 63;}
  2497.    { Long Echo
  2498.     ---------- }
  2499.    { FeedBack := 50;
  2500.     NumReverbs := 1;
  2501.     Reverb[0].Delay := 350;
  2502.     Reverb[0].Gain := -50; }
  2503.    { Alpia Echo
  2504.     ----------- }
  2505.    { FeedBack := 0;
  2506.     NumReverbs := 1;
  2507.     Reverb[0].Delay := 750;
  2508.     Reverb[0].Gain := 62; }
  2509.    { Double Echo
  2510.     ------------ }
  2511.    { FeedBack := 0;
  2512.     NumReverbs := 2;
  2513.     Reverb[0].Delay := 100;
  2514.     Reverb[0].Gain := -62;
  2515.     Reverb[1].Delay := 200;
  2516.     Reverb[1].Gain := 31; }
  2517.    { Alien 1
  2518.     -------- }
  2519.    { FeedBack := 47;
  2520.     NumReverbs := 3;
  2521.     Reverb[0].Delay := 10;
  2522.     Reverb[0].Gain := 47;
  2523.     Reverb[1].Delay := 28;
  2524.     Reverb[1].Gain := -27;
  2525.     Reverb[2].Delay := 55;
  2526.     Reverb[2].Gain := 42; }
  2527.    { Alien 2
  2528.     -------- }
  2529.     {FeedBack := 47;
  2530.     NumReverbs := 5;
  2531.     Reverb[0].Delay := 10;
  2532.     Reverb[0].Gain := 47;
  2533.     Reverb[1].Delay := 28;
  2534.     Reverb[1].Gain := -27;
  2535.     Reverb[2].Delay := 55;
  2536.     Reverb[2].Gain := 42;
  2537.     Reverb[3].Delay := 14;
  2538.     Reverb[3].Gain := 47;
  2539.     Reverb[4].Delay := 12;
  2540.     Reverb[4].Gain := 16; }
  2541.    { Strange FeedBack 1
  2542.     ------------------- }
  2543.     {FeedBack := 63;
  2544.     NumReverbs := 2;
  2545.     Reverb[0].Delay := 10;
  2546.     Reverb[0].Gain := -66;
  2547.     Reverb[1].Delay := 11;
  2548.     Reverb[1].Gain := 75;}
  2549.    { Strange FeedBack 2
  2550.     ------------------- }
  2551.    { FeedBack := 55;
  2552.     NumReverbs := 3;
  2553.     Reverb[0].Delay := 10;
  2554.     Reverb[0].Gain := -56;
  2555.     Reverb[1].Delay := 11;
  2556.     Reverb[1].Gain := 63;
  2557.     Reverb[2].Delay := 12;
  2558.     Reverb[2].Gain := -40;}
  2559.    { Strange FeedBack 3
  2560.     ------------------- }
  2561.    { FeedBack := 62;
  2562.     NumReverbs := 2;
  2563.     Reverb[0].Delay := 15;
  2564.     Reverb[0].Gain := -66;
  2565.     Reverb[1].Delay := 16;
  2566.     Reverb[1].Gain := 64; }
  2567.    { FeedBack Overload
  2568.     ------------------ }
  2569.    { FeedBack := 78;
  2570.     NumReverbs := 4;
  2571.     Reverb[0].Delay := 100;
  2572.     Reverb[0].Gain := 39;
  2573.     Reverb[1].Delay := 150;
  2574.     Reverb[1].Gain := -31;
  2575.     Reverb[2].Delay := 200;
  2576.     Reverb[2].Gain := 42;
  2577.     Reverb[3].Delay := 250;
  2578.     Reverb[3].Gain := -23;}
  2579. //    SetReverb(prvb, False, 90, 0, 100, FeedBack, NumReverbs, @Reverb);
  2580. *)
  2581. (*
  2582. //    SetPhaser(pph,50,CH_LEFT);
  2583. //                     Dry Wet   FB   Sweep   Depth, Rate,
  2584. //  SetPhaseShift(pps, 70, 70,   0,   100,     4,    1); // Phase shift
  2585. //  SetPhaseShift(pps, 99,  -99, -60, 100,     6,    0.2); // Slow invert phase shift w FB
  2586. //                  Dry Wet   FB   Delay  Depth, Rate,
  2587. //  SetFlanger(pfc, 50, 50, 70,  250,    0,    0.0); // Echoes
  2588.   SetFlanger(pfc, 50, 50,  0,    0,    6,    2.0); // Slow Flange
  2589. //  SetFlanger(pfc, 50,-50,-70,    0,    6,    2.0); // Slow invert flange w FB
  2590. //    SetFlanger(pfc, 50, 50,  0,   20,   20,   11.0); // Slow Chorus
  2591. *)