MMFX.pas
上传用户:hylc_2004
上传日期:2014-01-23
资源大小:46800k
文件大小:94k
- {========================================================================}
- {= (c) 1995-98 SwiftSoft Ronald Dittrich =}
- {========================================================================}
- {= All Rights Reserved =}
- {========================================================================}
- {= D 01099 Dresden = Fax.: +49 (0)351-8037944 =}
- {= Loewenstr.7a = info@swiftsoft.de =}
- {========================================================================}
- {= Actual versions on http://www.swiftsoft.de/mmtools.html =}
- {========================================================================}
- {= This code is for reference purposes only and may not be copied or =}
- {= distributed in any format electronic or otherwise except one copy =}
- {= for backup purposes. =}
- {= =}
- {= No Delphi Component Kit or Component individually or in a collection=}
- {= subclassed or otherwise from the code in this unit, or associated =}
- {= .pas, .dfm, .dcu, .asm or .obj files may be sold or distributed =}
- {= without express permission from SwiftSoft. =}
- {= =}
- {= For more licence informations please refer to the associated =}
- {= HelpFile. =}
- {========================================================================}
- {= $Date: 06.09.98 - 13:22:36 $ =}
- {========================================================================}
- unit MMFX;
- {$I COMPILER.INC}
- interface
- uses
- Windows,
- SysUtils,
- MMSystem,
- MMUtils,
- MMRegs,
- MMMulDiv,
- MMMath;
- {========================================================================}
- const
- { constants for the DataType fields }
- DT_8BIT = $00; { x0 b }
- DT_16BIT = $01; { x1 b }
- DT_MONO = $00; { 0x b }
- DT_STEREO = $02; { 1x b }
- { constants for channels }
- CH_BOTH = $00;
- CH_LEFT = $01;
- CH_RIGHT = $02;
- function GetDataType(pwfx: PWaveFormatEx): integer;
- {========================================================================}
- const
- FT_NONE = 0;
- FT_SOFTLOWPASS = 1;
- FT_LOWPASS = 2;
-
- type
- PSimpleFilter = ^TSimpleFilter;
- TSimpleFilter = packed record
- FilterType: integer; { FT_NON,FT_SOFTLOWPASS,FT_LOWPASS }
- DataType : integer; { DT_8BIT,DT_16BIT,DT_MONO,DT_STEREO }
- PrevValL : SmallInt; { internal, last sample left channel }
- PrevValR : SmallInt; { internal, last sample right channel }
- end;
- function InitSimpleLowPass(pwfx: PWaveFormatEx): PSimpleFilter;
- procedure DoneSimpleLowPass(var pf: PSimpleFilter);
- procedure SetSimpleLowPass(pf: PSimpleFilter; FilterTyp: integer);
- procedure DoSimpleLowPass(pf: PSimpleFilter; Buf: PChar; Len: Longint); pascal;
- {========================================================================}
- const
- MaxEchos = 8;
- type
- PEcho = ^TEcho;
- TEcho = record
- Delay: Longint; { delay (ms) for this echo line }
- Gain : Longint; { mix volume (%) for this echo }
- end;
- PEchoArray = ^TEchoArray;
- TEchoArray = array[0..MaxEchos-1] of TEcho;
- PReverbParm = ^TReverbParm; { Internal for the reverb engine }
- TReverbParm = record
- Position : Longint;
- Gain : Longint;
- end;
- PReverb = ^TReverb;
- TReverb = packed record
- InputGain : Longint; { Input Gain for the signal (%) }
- InputPan : Longint; { Inp. Pan add 0..100 % to other chan.}
- OutputGain : Longint; { mix gain for the echos (%) }
- OutputFilter: LongBool; { enable/disable Low pass filter }
- FeedBack : Longint; { Feedback value for reverb (%) }
- DataType : integer; { DT_8BIT,DT_16BIT,DT_MONO,DT_STEREO }
- SampleRate : Longint; { SampleRate for the samples }
- Count : integer; { number of reverbs 0..8 }
- Reverbs : array[0..MaxEchos-1] of TReverbParm;
- DLineL : PSmallArray; { Left DelayLine }
- DLineR : PSmallArray; { Right DelayLine }
- DLineSize : Longint; { max size for DelayLine }
- DLinePos : Longint; { current write position in DelayLine }
- PrevValL : Longint; { internal, last sample left channel }
- PrevValR : Longint; { internal, last sample right channel }
- MaxDelay : integer; { the maximal allowed delay (ms) }
- end;
- function InitReverb(pwfx: PWaveFormatEx; MaxDelay: integer): PReverb;
- procedure DoneReverb(var prvb: PReverb);
- procedure SetReverb(prvb: PReverb; Filter: Boolean; InputGain, InputPan,
- OutputGain, FeedBack, NumReverbs: integer;
- NewReverbs: PEchoArray);
- function DoReverb(prvb: PReverb; Buf: PChar; Len: Longint): Boolean; pascal;
- {========================================================================}
- type
- PDelay = ^TDelay;
- TDelay = packed record
- DataType : integer; { DT_8BIT,DT_16BIT,DT_MONO,DT_STEREO }
- SampleRate : Longint; { SampleRate for the samples }
- DLineL : PSmallArray; { Left DelayLine }
- DLineR : PSmallArray; { Right DelayLine }
- DLineSize : Longint; { max size for DelayLine }
- DLinePos : Longint; { current write position in DelayLine }
- PositionL : Longint; { current read position in DelayLine }
- PositionR : Longint; { current read position in DelayLine }
- MaxDelay : integer; { the maximal allowed delay (ms) }
- end;
- function InitDelay(pwfx: PWaveFormatEx; MaxDelay: integer): PDelay;
- procedure DoneDelay(var pdel: PDelay);
- procedure SetDelay(pdel: PDelay; DelayLeft, DelayRight: integer);
- procedure DoDelay(pdel: PDelay; Buf: PChar; Len: Longint); pascal;
- {========================================================================}
- type
- PPhaser = ^TPhaser;
- TPhaser = packed record
- DataType : integer; { DT_8BIT,DT_16BIT,DT_MONO,DT_STEREO }
- Channel : integer; { on which channel do the phase shift }
- SampleRate : Longint; { SampleRate for the samples }
- Position : Longint; { current outp.position in DelayLine }
- Delay : integer; { the current delay }
- DLine : PSmallArray; { DelayLine }
- DLineSize : Longint; { max size for DelayLine }
- DLinePos : Longint; { current inp. position in DelayLine }
- MaxDelay : integer; { the maximal allowed delay (ms) }
- Started : LongBool; { new phaser has started }
- RealTime : LongBool; { do special things for realtime phase}
- end;
- function InitPhaser(pwfx: PWaveFormatEx; MaxDelay: integer; RealTime: Boolean): PPhaser;
- procedure DonePhaser(var pph: PPhaser);
- procedure SetPhaser(pph: PPhaser; iDelay: integer; iChannel: integer);
- procedure DoPhaser(pph: PPhaser; Buf: PChar; Len: Longint); pascal;
- {========================================================================}
- type
- PPhaseShift = ^TPhaseShift;
- TPhaseShift = packed record
- DataType : integer; { DT_8BIT,DT_16BIT,DT_MONO,DT_STEREO }
- SampleRate : Longint; { SampleRate for the samples }
- FeedBack : Longint; { Feedback value for phaseshift (%) }
- DryMix : Longint; { dry (unaffected) signal mix (%) }
- WetMix : Longint; { wet (affected) signal mix (%) }
- Sweep : Float; { base frequency of sweep }
- Rate : Float; { rate of sweep in cycles per second }
- Depth : Float; { sweep range in octaves }
- { internal variables }
- wp,Min_wp,Max_wp,SweepFact: Float;
- inL1,outL1,inL2,outL2,inL3,outL3,inL4,outL4: Longint;
- inR1,outR1,inR2,outR2,inR3,outR3,inR4,outR4: Longint;
- end;
- function InitPhaseShift(pwfx: PWaveFormatEx): PPhaseShift;
- procedure DonePhaseShift(var pps: PPhaseShift);
- procedure SetPhaseShift(pps: PPhaseShift; iDry,iWet,iFeedBack: Longint;
- iSweep,iDepth,iRate: Float);
- function DoPhaseShift(pps: PPhaseShift; Buf: PChar; Len: Longint): Boolean;
- {========================================================================}
- type
- PFlanger = ^TFlanger;
- TFlanger = packed record
- DataType : integer; { DT_8BIT,DT_16BIT,DT_MONO,DT_STEREO }
- SampleRate : Longint; { SampleRate for the samples }
- FeedBack : Longint; { Feedback value for phaseshift (%) }
- DryMix : Longint; { dry (unaffected) signal mix (%) }
- WetMix : Longint; { wet (affected) signal mix (%) }
- Rate : Float; { rate of sweep in cycles per second }
- Depth : Float; { sweep range in octaves }
- Delay : integer; { the current delay (ms) }
- DLineL : PSmallArray; { Left DelayLine }
- DLineR : PSmallArray; { Right DelayLine }
- DLineSize : Longint; { max size for DelayLine }
- DLinePos : Longint; { current position in DelayLine }
- MaxDelay : integer; { the maximal allowed delay (ms) }
- { internal variables }
- ep1,ep2: integer;
- Sweep,MinSweep,MaxSweep,Step: Longint;
- end;
- function InitFlanger(pwfx: PWaveFormatEx; MaxDelay: integer): PFlanger;
- procedure DoneFlanger(var pfc: PFlanger);
- procedure SetFlanger(pfc: PFlanger; iDry,iWet,iFeedBack,
- iDelay: Longint; iDepth, iRate: Float);
- function DoFlanger(pfc: PFlanger; Buf: PChar; Len: Longint): Boolean;
- {========================================================================}
- const
- MAX_XTAB = 512; { crossfade lookup table size for pitch change }
- type
- PFadeArray = ^TFadeArray;
- TFadeArray = array[0..MAX_XTAB-1] of Float;
- PPitchChange = ^TPitchChange;
- TPitchChange = packed record
- DataType : integer; { DT_8BIT,DT_16BIT,DT_MONO,DT_STEREO }
- SampleRate : Longint; { SampleRate for the samples }
- FeedBack : Longint; { Feedback value for phaseshift (%) }
- DryMix : Longint; { dry (unaffected) signal mix (%) }
- WetMix : Longint; { wet (affected) signal mix (%) }
- Rate : Float; { rate of sweep in cycles per second }
- Depth : integer; { sweep range in octaves }
- Delay : integer; { the current delay (ms) }
- DLineL : PLongArray; { Left DelayLine }
- DLineR : PLongArray; { Right DelayLine }
- DLineSize : Longint; { max size for DelayLine }
- MaxDelay : integer; { the maximal allowed delay (ms) }
- { internal variables }
- fp,ep1,ep2,ep3,ep4: integer;
- MinSweep,MaxSweep: integer;
- Step,XFade,XFadeCnt,Active,ActiveCnt: integer;
- BlendA,BlendB: Float;
- FadeA,FadeB: PFadeArray;
- Fade_Out,Fade_In: TFadeArray;
- Sweep: Longint;
- SweepUp,ChanA: Boolean;
- end;
- function InitPitchChange(pwfx: PWaveFormatEx; MaxDelay: integer): PPitchChange;
- procedure DonePitchChange(var ppc: PPitchChange);
- procedure SetPitchChange(ppc: PPitchChange; iDry,iWet,iFeedBack,
- iDelay,iDepth: Longint; iRate: Float);
- procedure DoPitchChange(ppc: PPitchChange; Buffer: PChar; Len: Longint); pascal;
- implementation
- {========================================================================}
- function GetDataType(pwfx: PWaveFormatEx): Integer;
- begin
- Result := -1;
- if (pwfx <> Nil) and (pwfx^.wFormatTag = WAVE_FORMAT_PCM) then
- begin
- Result := 0;
- if (pwfx^.wBitsPerSample = 16) then Result := Result or DT_16BIT;
- if (pwfx^.nChannels = 2) then Result := Result or DT_STEREO;
- end;
- end;
- {========================================================================}
- { -- Simple Low Pass -- }
- {========================================================================}
- function InitSimpleLowPass(pwfx: PWaveFormatEx): PSimpleFilter;
- begin
- Result := GlobalAllocMem(sizeOf(TSimpleFilter));
- if (Result <> nil) then
- with Result^ do
- begin
- FilterType:= FT_NONE;
- DataType := GetDataType(pwfx);
- if (DataType and DT_16BIT = DT_16BIT) then
- begin
- PrevValL := 0;
- PrevValR := 0;
- end
- else
- begin
- PrevValL := 128;
- PrevValR := 128;
- end;
- end;
- end;
- {========================================================================}
- procedure DoneSimpleLowPass(var pf: PSimpleFilter);
- begin
- GlobalFreeMem(Pointer(pf));
- end;
- {========================================================================}
- procedure SetSimpleLowPass(pf: PSimpleFilter; FilterTyp: integer);
- begin
- if (pf <> nil) then
- with pf^ do
- begin
- FilterType:= FilterTyp;
- if (DataType and DT_16BIT = DT_16BIT) then
- begin
- PrevValL := 0;
- PrevValR := 0;
- end
- else
- begin
- PrevValL := 128;
- PrevValR := 128;
- end;
- end;
- end;
- {========================================================================}
- { Simple Low Pass Filter }
- { }
- { Algorithm: Type 1: y(n) := (x(n) + x(n-1))/2 }
- { Type 2: y(n) := (x(n)*3 + x(n-1))/4 }
- {========================================================================}
- {$IFDEF USEASM}
- {$L MMSLOWL.OBJ}
- {$F+}
- procedure DoSimpleLowPass(pf: PSimpleFilter; Buf: PChar; Len: Longint); external;
- {$F-}
- {$ELSE}
- procedure DoSimpleLowPass(pf: PSimpleFilter; Buf: PChar; Len: Longint);
- var
- pW: PSmallInt;
- pB: PByte;
- begin
- if (pf <> nil) then
- with pf^ do
- case FilterType of
- FT_SOFTLOWPASS:
- if (DataType and DT_STEREO = DT_STEREO) then { Stereo }
- begin
- if (DataType and DT_16BIT = DT_16BIT) then { 16-bit }
- begin
- pW := PSmallInt(Buf);
- while (Len > 0) do
- begin
- pW^ := (Longint(PrevValL)+pW^+pW^+pW^) shr 2;
- PrevValL := pW^;
- inc(pW);
- pW^ := (Longint(PrevValR)+pW^+pW^+pW^) shr 2;
- PrevValR := pW^;
- inc(pW);
- dec(Len,2*sizeOf(SmallInt));
- end;
- end
- else
- begin { 8-bit }
- pB := PByte(Buf);
- while (Len > 0) do
- begin
- pB^ := (PrevValL+pB^+pB^+pB^) shr 2;
- PrevValL := pB^;
- inc(pB);
- pB^ := (PrevValR+pB^+pB^+pB^) shr 2;
- PrevValR := pB^;
- inc(pB);
- dec(Len,2*sizeOf(Byte));
- end;
- end;
- end
- else { Mono }
- begin
- if (DataType and DT_16BIT = DT_16BIT) then { 16-bit }
- begin
- pW := PSmallInt(Buf);
- while (Len > 0) do
- begin
- pW^ := (Longint(PrevValL)+pW^+pW^+pW^)shr 2;
- PrevValL := pW^;
- inc(pW);
- dec(Len,sizeOf(SmallInt));
- end;
- end
- else { 8-bit }
- begin
- pB := PByte(Buf);
- while (Len > 0) do
- begin
- pB^ := (PrevValL+pB^+pB^+pB^) shr 2;
- PrevValL := pB^;
- inc(pB);
- dec(Len,sizeOf(Byte));
- end;
- end;
- end;
- FT_LOWPASS:
- if (DataType and DT_STEREO = DT_STEREO) then { Stereo }
- begin
- if (DataType and DT_16BIT = DT_16BIT) then { 16-bit }
- begin
- Len := (Len div 4) * 4;
- pW := PSmallInt(Buf);
- while Len > 0 do
- begin
- pW^ := (Longint(PrevValL)+pW^) shr 1;
- PrevValL := pW^;
- inc(pW);
- pW^ := (Longint(PrevValR)+pW^) shr 1;
- PrevValR := pW^;
- inc(pW);
- dec(Len,2*sizeOf(SmallInt));
- end;
- end
- else { 8 bit }
- begin
- Len := Len and $FFFE;
- pB := PByte(Buf);
- while (Len > 0) do
- begin
- pB^ := (PrevValL+pB^)shr 1;
- PrevValL := pB^;
- inc(pB);
- pB^ := (PrevValR+pB^)shr 1;
- PrevValR := pB^;
- inc(pB);
- dec(Len,2*sizeOf(Byte));
- end;
- end;
- end
- else { Mono }
- begin
- if (DataType and DT_16BIT = DT_16BIT) then { 16-bit }
- begin
- Len := Len and $FFFE;
- pW := PSmallInt(Buf);
- while (Len > 0) do
- begin
- pW^ := (Longint(PrevValL)+pW^) shr 1;
- PrevValL := pW^;
- inc(pW);
- dec(Len,sizeOf(SmallInt));
- end;
- end
- else
- begin { 8-bit }
- pB := PByte(Buf);
- while (Len > 0) do
- begin
- pB^ := (PrevValL+pB^) shr 1;
- PrevValL := pB^;
- inc(pB);
- dec(Len,sizeOf(Byte));
- end;
- end;
- end;
- end;
- end;
- {$ENDIF}
- {========================================================================}
- { -- Reverb -- }
- {========================================================================}
- function InitReverb(pwfx: PWaveFormatEx; MaxDelay: integer): PReverb;
- var
- i: integer;
- begin
- Result := GlobalAllocMem(SizeOf(TReverb));
- if (Result <> nil) then
- begin
- {$IFNDEF USEASM}
- MaxDelay := Min(MaxDelay,500);
- {$ENDIF}
- Result^.MaxDelay := MaxDelay;
- with Result^ do
- begin
- DataType := GetDataType(pwfx);
- SampleRate := pwfx^.nSamplesPerSec;
- Count := 0;
- InputGain := 100 * 256 div 100;
- InputPan := 50 * 256 div 100;
- OutputGain := 50 * 256 div 100;
- OutputFilter:= False;
- FeedBack := 0;
- DLineL := nil;
- DLineR := nil;
- DLinePos := 0;
- if (DataType and DT_16BIT = DT_16BIT) then
- begin
- PrevValL := 0;
- PrevValR := 0;
- end
- else
- begin
- PrevValL := 128;
- PrevValR := 128;
- end;
- { Calculate delay line size }
- DLineSize := SampleRate*MaxDelay div 1000;
- i := 0;
- while DLineSize > 2048 do
- begin
- DLineSize := DLineSize shr 1;
- inc(i);
- end;
- DLineSize := 2048;
- while i > 0 do
- begin
- DLineSize := DLineSize shl 1;
- dec(i);
- end;
- DLineL := GlobalAllocMem(DLineSize*sizeOf(SmallInt));
- if (DataType and DT_STEREO = DT_STEREO) then
- DLineR := GlobalAllocMem(DLineSize*sizeOf(SmallInt));
- if (DLineL = nil) or
- ((DLineR = nil) and (DataType and DT_STEREO = DT_STEREO)) then
- begin
- DoneReverb(Result);
- end;
- end;
- end;
- end;
- {========================================================================}
- procedure DoneReverb(var prvb: PReverb);
- begin
- if (prvb <> nil) then
- begin
- GlobalFreeMem(Pointer(prvb^.DLineL));
- GlobalFreeMem(Pointer(prvb^.DLineR));
- GlobalFreeMem(Pointer(prvb));
- end;
- end;
- {========================================================================}
- procedure SetReverb(prvb: PReverb; Filter: Boolean; InputGain, InputPan,
- Outputgain, FeedBack, NumReverbs: integer;
- NewReverbs: PEchoArray);
- var
- i: integer;
- begin
- if (prvb <> nil) then
- begin
- with prvb^ do
- begin
- if (DataType and DT_16BIT = DT_16BIT) then
- begin
- PrevValL := 0;
- PrevValR := 0;
- end
- else
- begin
- PrevValL := 128;
- PrevValR := 128;
- end;
- if (NumReverbs > 8) or (NumReverbs < 0) then exit;
- for i := 0 to NumReverbs-1 do { Check max delay for delay line }
- begin
- if (NewReverbs^[i].Delay > MaxDelay) then
- NewReverbs^[i].Delay := MaxDelay;
- end;
- if (DLineSize > 0) then
- begin
- FillChar(DLineL^,2*DLineSize,0); { Clear delay lines }
- if (DataType and DT_STEREO = DT_STEREO) then
- FillChar(DLineR^,2*DLineSize,0);
- end;
- for i := 0 to NumReverbs-1 do { Adjust reverbs }
- begin
- Reverbs[i].Position := DLineSize-Max(Long(SampleRate)*NewReverbs^[i].Delay div 1000,1);
- Reverbs[i].Gain := NewReverbs^[i].Gain * 256 div 100;
- end;
- Count := NumReverbs;
- DLinePos := 0;
- end;
- prvb^.InputGain:= InputGain * 256 div 100;
- prvb^.InputPan := InputPan * 256 div 100;
- prvb^.OutputGain := OutputGain * 256 div 100;
- prvb^.OutputFilter := Filter;
- prvb^.Feedback := Feedback * 256 div 100;
- end;
- end;
- {========================================================================}
- { FeedBack }
- { ______ +--------------------<---------------------------+ }
- { IN | INP | | Direct Signal ___ | }
- { --->| GAIN |-+-------------------->------------------->| + | | }
- { |______| | | | | OUT }
- { | | |--+---> }
- { +--------+ | + | }
- { | _________ _________ ___ |___| }
- { | | | | | * a | | ______ | }
- { +-->| Delay 1 |-->| Gain 1 |----->| + | | OUT | | }
- { | |_________| |_________| | |-->| GAIN |--+ }
- { | _________ _________ | | |______| }
- { | | | | | * b | | }
- { +-->| Delay 2 |-->| Gain 2 |----->| + | }
- { | |_________| |_________| | | }
- { | | | }
- { +--> .... | | }
- {========================================================================}
- {$IFDEF USEASM}
- {$L MMREVBL.OBJ}
- {$F+}
- var
- Reverb: TReverb;
- PrevvalOutL: Longint;
- PrevvalOutR: Longint;
- function DoReverb(prvb: PReverb; Buf: PChar; Len: Longint): Boolean; external;
- {$F-}
- {$ELSE}
- function DoReverb(prvb: PReverb; Buf: PChar; Len: Longint): Boolean;
- var
- mask,t: integer;
- pW: PSmallint;
- pB: PByte;
- revval,outvalL,outvalR,tempval: Longint;
- begin
- { returns true on internal overflow }
- Result := False;
- if (prvb <> nil) and (prvb^.Count > 0) then
- with prvb^ do
- begin
- mask := DLineSize-1; { Mask to prevent delay line overflow }
- if (DataType and DT_STEREO = DT_STEREO) then { stereo }
- begin
- if (DataType and DT_16BIT = DT_16BIT) then { 16-bit }
- begin
- Len := Len div 4 * 4;
- pW := PSmallint(Buf);
- while (Len > 0) do
- begin { Process left }
- outvalL := sar(pW^*InputGain,8);
- outvalR := sar(PSmallInt(PChar(pW)+sizeOf(SmallInt))^*InputGain,8);
- revval := 0;
- for t := 0 to Count-1 do
- begin
- revval := revval + (Reverbs[t].Gain*DLineL^[Reverbs[t].Position]);
- end;
- revval := sar(PrevValL + sar(revval,8),1);
- PrevValL := revval;
- tempval := outvalL + sar(outvalR*InputPan,8) + sar(revval*Feedback,8);
- revval := outvalL + sar(revval*OutputGain,8);
- if (revval > 32767) then
- begin
- Result := True;
- revval := 32767
- end
- else if (revval < -32767) then
- begin
- Result := True;
- revval := -32767;
- end;
- if (tempval > 32767) then
- begin
- Result := True;
- tempval := 32767;
- end
- else if (tempval < -32767) then
- begin
- Result := True;
- tempval := -32767;
- end;
- DLineL^[DLinePos] := tempval;
- pW^ := SmallInt(revval);
- inc(pW);
- { Process right }
- revval := 0;
- for t := 0 to Count-1 do
- begin
- revval := revval + (reverbs[t].gain*DLineR^[reverbs[t].Position]);
- Reverbs[t].Position := (reverbs[t].Position + 1) and mask;
- end;
- revval := sar(PrevValR+sar(revval,8),1);
- PrevValR := revval;
- tempval := outvalR + sar(outvalL*InputPan,8) + sar(revval*Feedback,8);
- revval := outvalR + sar(revval*OutputGain,8);
- if (revval > 32767) then
- begin
- Result := True;
- revval := 32767
- end
- else if (revval < -32767) then
- begin
- Result := True;
- revval := -32767;
- end;
- if (tempval > 32767) then
- begin
- Result := True;
- tempval := 32767;
- end
- else if (tempval < -32767) then
- begin
- Result := True;
- tempval := -32767;
- end;
- DLineR^[DLinePos] := tempval;
- pW^ := revval;
- inc(pW);
- DLinePos := (DLinePos + 1) and mask;
- dec(Len,2*sizeOf(SmallInt));
- end;
- end
- else { 8-bit stereo }
- begin
- Len := Len and $FFFE;
- pB := PByte(Buf);
- while (Len > 0) do
- begin { Process left }
- outvalL := sar(((pB^-128) shl 8)*InputGain,8);
- outvalR := sar(((PByte(PChar(pB)+sizeOf(Byte))^-128)shl 8)*InputGain,8);
- revval := 0;
- for t := 0 to Count-1 do
- begin
- revval := revval + (reverbs[t].gain*DLineL^[reverbs[t].position]);
- end;
- revval := sar(PrevValL+sar(revval,8),1);
- PrevValL := revval;
- tempval := outvalL+sar(outvalR*InputPan,8)+sar(revval*Feedback,8);
- revval := outvalL + sar(revval*OutputGain,8);
- if (revval > 32767) then
- begin
- Result := True;
- revval := 32767
- end
- else if (revval < -32767) then
- begin
- Result := True;
- revval := -32767;
- end;
- if (tempval > 32767) then
- begin
- Result := True;
- tempval := 32767;
- end
- else if (tempval < -32767) then
- begin
- Result := True;
- tempval := -32767;
- end;
- DLineL^[DLinePos] := tempval;
- pB^ := (revval shr 8) + 128;
- inc(pB);
- { Process right }
- revval := 0;
- for t := 0 to Count-1 do
- begin
- revval := revval + (reverbs[t].gain*DLineR^[reverbs[t].position]);
- reverbs[t].position := (reverbs[t].position + 1) and mask;
- end;
- revval := sar(PrevValR+sar(revval,8),1);
- PrevValR := revval;
- tempval := outvalR+sar(outvalL*InputPan,8)+sar(revval*Feedback,8);
- revval := outvalR + sar(revval*OutputGain,8);
- if (revval > 32767) then
- begin
- Result := True;
- revval := 32767
- end
- else if (revval < -32767) then
- begin
- Result := True;
- revval := -32767;
- end;
- if (tempval > 32767) then
- begin
- Result := True;
- tempval := 32767;
- end
- else if (tempval < -32767) then
- begin
- Result := True;
- tempval := -32767;
- end;
- DLineR^[DLinePos] := tempval;
- pB^ := (revval shr 8) + 128;
- inc(pB);
- DLinePos := (DLinePos+1) and mask;
- dec(Len,2*sizeOf(Byte));
- end;
- end;
- end
- else { Mono reverb }
- begin
- if (dataType and DT_16BIT = DT_16BIT) then { 16-bit Mono }
- begin
- Len := Len and $FFFE;
- pW := PSmallint(Buf);
- while (Len > 0) do
- begin
- outvalL := sar(pW^*InputGain,8);
- revval := 0;
- for t := 0 to Count-1 do
- begin
- revval := revval + (reverbs[t].gain*DLineL^[reverbs[t].position]);
- reverbs[t].position := (reverbs[t].position + 1) and mask;
- end;
- revval := sar(PrevValL+sar(revval,8),1);
- PrevValL := revval;
- tempval := outvalL+sar(revval*Feedback,8);
- revval := outvalL + sar(revval*OutputGain,8);
- if (revval > 32767) then
- begin
- Result := True;
- revval := 32767
- end
- else if (revval < -32767) then
- begin
- Result := True;
- revval := -32767;
- end;
- if (tempval > 32767) then
- begin
- Result := True;
- tempval := 32767;
- end
- else if (tempval < -32767) then
- begin
- Result := True;
- tempval := -32767;
- end;
- DLineL^[DLinePos] := tempval;
- pW^ := revval;
- inc(pW);
- DLinePos := (DLinePos+1) and mask;
- dec(Len,sizeOf(SmallInt));
- end;
- end
- else
- begin
- pB := PByte(Buf); { 8-bit Mono }
- while (Len > 0) do
- begin
- outvalL := sar(((pB^-128) shl 8)*InputGain,8);
- revval := 0;
- for t := 0 to Count-1 do
- begin
- revval := revval + (reverbs[t].gain*DLineL^[reverbs[t].position]);
- reverbs[t].position := (reverbs[t].position + 1) and mask;
- end;
- revval := sar(PrevValL+sar(revval,8),1);
- PrevValL := revval;
- tempval := outvalL+sar(revval*Feedback,8);
- revval := outvalL + sar(revval*OutputGain,8);
- if (revval > 32767) then
- begin
- Result := True;
- revval := 32767
- end
- else if (revval < -32767) then
- begin
- Result := True;
- revval := -32767;
- end;
- if (tempval > 32767) then
- begin
- Result := True;
- tempval := 32767;
- end
- else if (tempval < -32767) then
- begin
- Result := True;
- tempval := -32767;
- end;
- DLineL^[DLinePos] := tempval;
- pB^ := (revval shr 8) + 128;
- inc(pB);
- DLinePos := (DLinePos+1) and mask;
- dec(Len,sizeOf(Byte));
- end;
- end;
- end;
- end;
- end;
- {$ENDIF}
- {========================================================================}
- { -- Delay -- }
- {========================================================================}
- function InitDelay(pwfx: PWaveFormatEx; MaxDelay: integer): PDelay;
- var
- i: integer;
- begin
- Result := GlobalAllocMem(SizeOf(TDelay));
- if (Result <> nil) then
- begin
- {$IFNDEF USEASM}
- MaxDelay := Min(MaxDelay,500);
- {$ENDIF}
- Result^.MaxDelay := MaxDelay;
- with Result^ do
- begin
- DataType := GetDataType(pwfx);
- SampleRate := pwfx^.nSamplesPerSec;
- DLineL := nil;
- DLineR := nil;
- DLinePos := 0;
- { Calculate delay line size }
- DLineSize := SampleRate*MaxDelay div 1000;
- i := 0;
- while DLineSize > 2048 do
- begin
- DLineSize := DLineSize shr 1;
- inc(i);
- end;
- DLineSize := 2048;
- while i > 0 do
- begin
- DLineSize := DLineSize shl 1;
- dec(i);
- end;
- DLineL := GlobalAllocMem(DLineSize*sizeOf(SmallInt));
- if (DataType and DT_STEREO = DT_STEREO) then
- DLineR := GlobalAllocMem(DLineSize*sizeOf(SmallInt));
- if (DLineL = nil) or
- ((DLineR = nil) and (DataType and DT_STEREO = DT_STEREO)) then
- begin
- DoneDelay(Result);
- end;
- end;
- end;
- end;
- {========================================================================}
- procedure DoneDelay(var pdel: PDelay);
- begin
- if (pdel <> nil) then
- begin
- GlobalFreeMem(Pointer(pdel^.DLineL));
- GlobalFreeMem(Pointer(pdel^.DLineR));
- GlobalFreeMem(Pointer(pdel));
- end;
- end;
- {========================================================================}
- procedure SetDelay(pdel: PDelay; DelayLeft, DelayRight: integer);
- begin
- if (pdel <> nil) then
- begin
- with pdel^ do
- begin
- { Check max delay for delay line }
- if (DelayLeft > MaxDelay) then
- DelayRight := MaxDelay;
- if (DelayRight > MaxDelay) then
- DelayRight := MaxDelay;
- if (DLineSize > 0) then
- begin
- FillChar(DLineL^,DLineSize*sizeOf(SmallInt),0); { Clear delay lines }
- if (DataType and DT_STEREO = DT_STEREO) then
- FillChar(DLineR^,DLineSize*sizeOf(SmallInt),0);
- end;
- PositionL := DLineSize-Max(Long(SampleRate)*DelayLeft div 1000,1);
- PositionR := DLineSize-Max(Long(SampleRate)*DelayRight div 1000,1);
- DLinePos := 0;
- end;
- end;
- end;
- {========================================================================}
- {$IFDEF USEASM}
- {$L MMDELL.OBJ}
- {$F+}
- var
- Delay: TDelay;
- procedure DoDelay(pdel: PDelay; Buf: PChar; Len: Longint); external;
- {$F-}
- {$ELSE}
- procedure DoDelay(pdel: PDelay; Buf: PChar; Len: Longint);
- var
- mask: integer;
- pW: PSmallint;
- pB: PByte;
- begin
- if (pdel <> nil) then
- with pdel^ do
- begin
- mask := DLineSize-1; { Mask to prevent delay line overflow }
- if (DataType and DT_STEREO = DT_STEREO) then { stereo }
- begin
- if (DataType and DT_16BIT = DT_16BIT) then { 16-bit }
- begin
- Len := Len div 4 * 4;
- pW := PSmallint(Buf);
- while (Len > 0) do
- begin { Process left }
- DLineL^[DLinePos] := pW^;
- pW^ := DLineL^[PositionL];
- PositionL := (PositionL + 1) and mask;
- inc(pW);
- { Process right }
- DLineR^[DLinePos] := pW^;
- pW^ := DLineR^[PositionR];
- PositionR := (PositionR + 1) and mask;
- inc(pW);
- DLinePos := (DLinePos + 1) and mask;
- dec(Len,2*sizeOf(SmallInt));
- end;
- end
- else { 8-bit stereo }
- begin
- Len := Len and $FFFE;
- pB := PByte(Buf);
- while (Len > 0) do
- begin { Process left }
- DLineL^[DLinePos] := (pB^-128) shl 8;
- pB^ := (DLineL^[PositionL] shr 8)+128;
- PositionL := (PositionL + 1) and mask;
- inc(pB);
- { Process right }
- DLineR^[DLinePos] := (pB^-128) shl 8;
- pB^ := (DLineR^[PositionR] shr 8)+128;
- PositionR := (PositionR + 1) and mask;
- inc(pB);
- DLinePos := (DLinePos + 1) and mask;
- dec(Len,2*sizeOf(Byte));
- end;
- end;
- end
- else { Mono reverb }
- begin
- if (dataType and DT_16BIT = DT_16BIT) then { 16-bit Mono }
- begin
- Len := Len and $FFFE;
- pW := PSmallint(Buf);
- while (Len > 0) do
- begin
- DLineL^[DLinePos] := pW^;
- pW^ := DLineL^[PositionL];
- PositionL := (PositionL + 1) and mask;
- inc(pW);
- DLinePos := (DLinePos + 1) and mask;
- dec(Len,sizeOf(SmallInt));
- end;
- end
- else
- begin
- pB := PByte(Buf); { 8 -bit Mono }
- while (Len > 0) do
- begin
- DLineL^[DLinePos] := (pB^-128) shl 8;
- pB^ := (DLineL^[PositionL] shr 8)+128;
- PositionL := (PositionL + 1) and mask;
- inc(pB);
- DLinePos := (DLinePos + 1) and mask;
- dec(Len,sizeOf(Byte));
- end;
- end;
- end;
- end;
- end;
- {$ENDIF}
- {========================================================================}
- { -- Phaser -- }
- {========================================================================}
- function InitPhaser(pwfx: PWaveFormatEx; MaxDelay: integer; RealTime: Boolean): PPhaser;
- var
- i: integer;
- begin
- Result := GlobalAllocMem(SizeOf(TPhaser));
- if (Result <> nil) then
- begin
- {$IFNDEF USEASM}
- MaxDelay := Min(MaxDelay,500);
- {$ENDIF}
- Result^.MaxDelay := MaxDelay;
- Result^.RealTime := RealTime;
- with Result^ do
- begin
- DataType := GetDataType(pwfx);
- Channel := CH_BOTH;
- SampleRate := pwfx^.nSamplesPerSec;
- Delay := 0;
- Position := 0;
- Started := False;
- DLine := nil;
- DLinePos := -1;
- { Calculate delay line size }
- DLineSize := SampleRate*MaxDelay div 1000;
- i := 0;
- while DLineSize > 2048 do
- begin
- DLineSize := DLineSize shr 1;
- inc(i);
- end;
- DLineSize := 2048;
- while i > 0 do
- begin
- DLineSize := DLineSize shl 1;
- dec(i);
- end;
- DLine := GlobalAllocMem(2*DLineSize);
- if (DLine = nil) then
- begin
- DonePhaser(Result);
- end;
- end;
- end;
- end;
- {========================================================================}
- procedure DonePhaser(var pph: PPhaser);
- begin
- if (pph <> nil) then
- begin
- GlobalFreeMem(Pointer(pph^.DLine));
- GlobalFreeMem(Pointer(pph));
- end;
- end;
- {========================================================================}
- procedure SetPhaser(pph: PPhaser; iDelay: integer; iChannel: integer);
- var
- Silence: integer;
- begin
- if (pph <> nil) then
- begin
- with pph^ do
- begin
- Delay := Min(iDelay,MaxDelay);
- Channel := iChannel;
- if (DLineSize > 0) then
- begin
- if (DataType and DT_16BIT = DT_16BIT) then
- Silence := 0
- else
- Silence := 128;
- FillChar(DLine^,2*DLineSize,Silence); { Clear delay line }
- end;
- { Adjust phaser }
- Position := DLineSize-Long(SampleRate)*Delay div 1000-1;
- DLinePos := -1;
- if RealTime then Started := True;
- end;
- end;
- end;
- {========================================================================}
- {$IFDEF USEASM}
- {$L MMPHASL.OBJ}
- {$F+}
- procedure DoPhaser(pph: PPhaser; Buf: PChar; Len: Longint); external;
- {$F-}
- {$ELSE}
- procedure DoPhaser(pph: PPhaser; Buf: PChar; Len: Longint);
- var
- pW: PSmallInt;
- pB: PByte;
- mask: integer;
- begin
- if (pph <> nil) and (pph^.Delay > 0) and
- (pph^.DataType and DT_STEREO = DT_STEREO) and
- (pph^.Channel <> 0) then
- with pph^ do
- begin
- mask := DLineSize-1;
- if (DataType and DT_16BIT = DT_16BIT) then { 16-bit }
- begin
- Len := (Len div 4) * 4;
- pW := PSmallInt(Buf);
- if (Channel and CH_RIGHT = CH_RIGHT) then inc(pW);
- while Len > 0 do
- begin
- DLinePos := (DLinePos+1) and mask;
- DLine^[DLinePos] := pW^;
- Position := (Position + 1) and mask;
- if not Started then pW^ := DLine^[Position]
- else if (Position = 0) then Started := False;
- inc(pW,2);
- dec(Len,2*sizeOf(SmallInt));
- end;
- end
- else { 8 bit }
- begin
- Len := Len and $FFFE;
- pB := PByte(Buf);
- if (Channel and CH_RIGHT = CH_RIGHT) then inc(pB);
- while (Len > 0) do
- begin
- DLinePos := (DLinePos+1) and mask;
- DLine^[DLinePos] := pB^;
- Position := (Position + 1) and mask;
- if not Started then pB^ := DLine^[Position]
- else if (Position = 0) then Started := False;
- inc(pB,2);
- dec(Len,2*sizeOf(Byte));
- end;
- end;
- end;
- end;
- {$ENDIF}
- {========================================================================}
- { -- PhaseShift -- }
- { }
- { Digital version of the popular '70s effect. This one }
- { does 4 stages just like old MXR Phase 90 stompbox. }
- {========================================================================}
- function InitPhaseShift(pwfx: PWaveFormatEx): PPhaseShift;
- begin
- Result := GlobalAllocMem(SizeOf(TPhaseShift));
- if (Result <> nil) then
- begin
- with Result^ do
- begin
- DataType := GetDataType(pwfx);
- SampleRate:= pwfx^.nSamplesPerSec;
- DryMix := 50 * 256 div 100;
- WetMix := 50 * 256 div 100;
- end;
- end;
- end;
- {========================================================================}
- procedure DonePhaseShift(var pps: PPhaseShift);
- begin
- if (pps <> nil) then
- begin
- GlobalFreeMem(Pointer(pps));
- end;
- end;
- {========================================================================}
- procedure SetPhaseShift(pps: PPhaseShift; iDry,iWet,iFeedBack: Longint;
- iSweep,iDepth,iRate: Float);
- var
- Range: Float;
- begin
- if (pps <> nil) then
- begin
- with pps^ do
- begin
- FeedBack:= iFeedBack * 256 div 100;
- DryMix := iDry * 256 div 100;
- WetMix := iWet * 256 div 100;
- Sweep := iSweep;
- Depth := iDepth;
- { calc params for sweeping filters }
- Range := pow(2.0, iDepth);
- Max_wp := (M_PI * iSweep * Range) / SampleRate;
- Min_wp := (M_PI * iSweep) / SampleRate;
- wp := Min_wp;
- Rate := pow(Range, iRate / (SampleRate / 2));
- SweepFact := Rate;
- { reset some things }
- inL1 := 0;
- inL2 := 0;
- inL3 := 0;
- inL4 := 0;
- outL1 := 0;
- outL2 := 0;
- outL3 := 0;
- outL4 := 0;
- end;
- end;
- end;
- {========================================================================}
- function DoPhaseShift(pps: PPhaseShift; Buf: PChar; Len: Longint): Boolean;
- var
- pW: PSmallInt;
- pB: PByte;
- coef: Longint;
- inval,outval: Longint;
- begin
- Result := False;
- if (pps <> nil) then
- with pps^ do
- begin
- if (DataType and DT_STEREO = DT_STEREO) then { stereo }
- begin
- if (DataType and DT_16BIT = DT_16BIT) then { 16-bit }
- begin
- pW := PSmallInt(Buf);
- while Len > 0 do
- begin
- { calc coef for current freq }
- coef := Trunc(8192*(1.0- wp)/(1.0 + wp));
- inval := pW^ + sar(outL4 * Feedback,8);
- { do 1st filter }
- outL1 := sar(coef*(outL1 + inval),13) - inL1;
- inL1 := inval;
- { do 2nd filter }
- outL2 := sar(coef*(outL2 + outL1),13) - inL2;
- inL2 := outL1;
- { do 3rd filter }
- outL3 := sar(coef*(outL3 + outL2),13) - inL3;
- inL3 := outL2;
- { do 4th filter }
- outL4 := sar(coef*(outL4 + outL3),13) - inL4;
- inL4 := outL3;
- { develop final output mix }
- outval := sar(outL4*WetMix,8);
- outval := outval+ sar(inval*DryMix,8);
- { clip output if necessary }
- if (outval > 32767) then
- begin
- pW^ := 32767;
- Result := True;
- end
- else if (outval < -32768) then
- begin
- pW^ := -32768;
- Result := True;
- end
- else pW^ := outval;
- inc(pW);
- inval := pW^+ sar(outR4 * Feedback,8);
- { do 1st filter }
- outR1 := sar(coef*(outR1 + inval),13) - inR1;
- inR1 := inval;
- { do 2nd filter }
- outR2 := sar(coef*(outR2 + outR1),13) - inR2;
- inR2 := outR1;
- { do 3rd filter }
- outR3 := sar(coef*(outR3 + outR2),13) - inR3;
- inR3 := outR2;
- { do 4th filter }
- outR4 := sar(coef*(outR4 + outR3),13) - inR4;
- inR4 := outR3;
- { develop final output mix }
- outval := sar(outR4*WetMix,8) + sar(inval*DryMix,8);
- { clip output if necessary }
- if (outval > 32767) then
- begin
- pW^ := 32767;
- Result := True;
- end
- else if (outval < -32768) then
- begin
- pW^ := -32768;
- Result := True;
- end
- else pW^ := outval;
- inc(pW);
- wp := wp * SweepFact; { adjust freq of filters }
- if (wp > Max_wp) then { max? }
- SweepFact := 1.0/Rate { sweep back down }
- else if (wp < Min_wp) then { min? }
- SweepFact := Rate; { sweep back up }
- dec(Len,2*sizeOf(SmallInt));
- end;
- end
- else
- begin
- pB := PByte(Buf);
- while Len > 0 do
- begin
- { calc coef for current freq }
- coef := Trunc(8192*(1.0 - wp)/(1.0 + wp));
- inval := (pB^-128)shl 8 + sar(outL4 * Feedback,8);
- { do 1st filter }
- outL1 := sar(coef*(outL1 + inval),13) - inL1;
- inL1 := inval;
- { do 2nd filter }
- outL2 := sar(coef*(outL2 + outL1),13) - inL2;
- inL2 := outL1;
- { do 3rd filter }
- outL3 := sar(coef*(outL3 + outL2),13) - inL3;
- inL3 := outL2;
- { do 4th filter }
- outL4 := sar(coef*(outL4 + outL3),13) - inL4;
- inL4 := outL3;
- { develop final output mix }
- outval := sar(outL4*WetMix,8) + sar(inval*DryMix,8);
- { clip output if necessary }
- if (outval > 32767) then
- begin
- pW^ := 32767;
- Result := True;
- end
- else if (outval < -32768) then
- begin
- pW^ := -32768;
- Result := True;
- end
- else pW^ := outval;
- pB^ := (outval shr 8)+128;
- inc(pB);
- inval := (pB^-128)shl 8 + sar(outR4 * Feedback,8);
- { do 1st filter }
- outR1 := sar(coef*(outR1 + inval),13) - inR1;
- inR1 := inval;
- { do 2nd filter }
- outR2 := sar(coef*(outR2 + outR1),13) - inR2;
- inR2 := outR1;
- { do 3rd filter }
- outR3 := sar(coef*(outR3 + outR2),13) - inR3;
- inR3 := outR2;
- { do 4th filter }
- outR4 := sar(coef*(outR4 + outR3),13) - inR4;
- inR4 := outR3;
- { develop final output mix }
- outval := sar(outR4*WetMix,8) + sar(inval*DryMix,8);
- { clip output if necessary }
- if (outval > 32767) then
- begin
- pW^ := 32767;
- Result := True;
- end
- else if (outval < -32768) then
- begin
- pW^ := -32768;
- Result := True;
- end
- else pW^ := outval;
- pB^ := (outval shr 8)+128;
- inc(pB);
- wp := wp * SweepFact; { adjust freq of filters }
- if (wp > Max_wp) then { max? }
- SweepFact := 1.0/Rate { sweep back down }
- else if (wp < Min_wp) then { min? }
- SweepFact := Rate; { sweep back up }
- dec(Len,2*sizeOf(Byte));
- end;
- end;
- end
- else { mono }
- begin
- if (DataType and DT_16BIT = DT_16BIT) then { 16-bit }
- begin
- pW := PSmallInt(Buf);
- while Len > 0 do
- begin
- { calc coef for current freq }
- coef := Trunc(8192*(1.0 - wp)/(1.0 + wp));
- inval := pW^ + sar(outL4 * Feedback,8);
- { do 1st filter }
- outL1 := sar(coef*(outL1 + inval),13) - inL1;
- inL1 := inval;
- { do 2nd filter }
- outL2 := sar(coef*(outL2 + outL1),13) - inL2;
- inL2 := outL1;
- { do 3rd filter }
- outL3 := sar(coef*(outL3 + outL2),13) - inL3;
- inL3 := outL2;
- { do 4th filter }
- outL4 := sar(coef*(outL4 + outL3),13) - inL4;
- inL4 := outL3;
- { develop final output mix }
- outval := sar(outL4*WetMix,8) + sar(inval*DryMix,8);
- { clip output if necessary }
- if (outval > 32767) then
- begin
- pW^ := 32767;
- Result := True;
- end
- else if (outval < -32768) then
- begin
- pW^ := -32768;
- Result := True;
- end
- else pW^ := outval;
- wp := wp * SweepFact; { adjust freq of filters }
- if (wp > Max_wp) then { max? }
- SweepFact := 1.0/Rate { sweep back down }
- else if (wp < Min_wp) then { min? }
- SweepFact := Rate; { sweep back up }
- inc(pW);
- dec(Len,sizeOf(SmallInt));
- end;
- end
- else
- begin
- pB := PByte(Buf);
- while Len > 0 do
- begin
- { calc coef for current freq }
- coef := Trunc(8192*(1.0 - wp)/(1.0 + wp));
- inval := (pB^-128)shl 8 + sar(outL4 * Feedback,8);
- { do 1st filter }
- outL1 := sar(coef*(outL1 + inval),13) - inL1;
- inL1 := inval;
- { do 2nd filter }
- outL2 := sar(coef*(outL2 + outL1),13) - inL2;
- inL2 := outL1;
- { do 3rd filter }
- outL3 := sar(coef*(outL3 + outL2),13) - inL3;
- inL3 := outL2;
- { do 4th filter }
- outL4 := sar(coef*(outL4 + outL3),13) - inL4;
- inL4 := outL3;
- { develop final output mix }
- outval := sar(outL4*WetMix,8) + sar(inval*DryMix,8);
- { clip output if necessary }
- if (outval > 32767) then
- begin
- pW^ := 32767;
- Result := True;
- end
- else if (outval < -32768) then
- begin
- pW^ := -32768;
- Result := True;
- end
- else pW^ := outval;
- pB^ := (outval shr 8)+128;
- wp := wp * SweepFact; { adjust freq of filters }
- if (wp > Max_wp) then { max? }
- SweepFact := 1.0/Rate { sweep back down }
- else if (wp < Min_wp) then { min? }
- SweepFact := Rate; { sweep back up }
- inc(pB);
- dec(Len,sizeOf(Byte));
- end;
- end;
- end;
- end;
- end;
- {========================================================================}
- { -- Flanger -- }
- {========================================================================}
- function InitFlanger(pwfx: PWaveFormatEx; MaxDelay: integer): PFlanger;
- var
- i: integer;
- begin
- Result := GlobalAllocMem(SizeOf(TFlanger));
- if (Result <> nil) then
- begin
- {$IFNDEF USEASM}
- MaxDelay := Min(MaxDelay,500);
- {$ENDIF}
- Result^.MaxDelay := MaxDelay;
- with Result^ do
- begin
- DataType := GetDataType(pwfx);
- SampleRate := pwfx^.nSamplesPerSec;
- Delay := 0;
- DLineL := nil;
- DLineR := nil;
- DLinePos := 0;
- { Calculate delay line size }
- DLineSize := SampleRate*MaxDelay div 1000;
- i := 0;
- while DLineSize > 2048 do
- begin
- DLineSize := DLineSize shr 1;
- inc(i);
- end;
- DLineSize := 2048;
- while i > 0 do
- begin
- DLineSize := DLineSize shl 1;
- dec(i);
- end;
- DLineL := GlobalAllocMem(DLineSize*sizeOf(Smallint));
- if (DataType and DT_STEREO = DT_STEREO) then
- DLineR := GlobalAllocMem(DLineSize*sizeof(Smallint));
- if (DLineL = nil) or
- ((DLineR = nil) and (DataType and DT_STEREO = DT_STEREO)) then
- begin
- DoneFlanger(Result);
- end;
- end;
- end;
- end;
- {========================================================================}
- procedure DoneFlanger(var pfc: PFlanger);
- begin
- if (pfc <> nil) then
- begin
- GlobalFreeMem(Pointer(pfc^.DLineL));
- GlobalFreeMem(Pointer(pfc^.DLineR));
- GlobalFreeMem(Pointer(pfc));
- end;
- end;
- {========================================================================}
- procedure SetFlanger(pfc: PFlanger; iDry,iWet,iFeedBack,
- iDelay: Longint; iDepth, iRate: Float);
- begin
- if (pfc <> nil) then
- begin
- with pfc^ do
- begin
- FeedBack:= iFeedBack * 256 div 100;
- DryMix := iDry * 256 div 100;
- WetMix := iWet * 256 div 100;
- Rate := iRate;
- Depth := iDepth;
- Step := Trunc(iRate * 65.536);
- Delay := iDelay;
- if (Delay > MaxDelay) then
- Delay := MaxDelay;
- if (DLineSize > 0) then
- begin
- FillChar(DLineL^,DLineSize*sizeOf(Smallint),0); { Clear delay lines }
- if (DataType and DT_STEREO = DT_STEREO) then
- FillChar(DLineR^,DLineSize*sizeOf(Smallint),0);
- end;
- DLinePos := 0;
- ep1 := 0;
- ep2 := 0;
- { init/calc some stuff }
- MaxSweep := DLineSize - (SampleRate * Delay div 1000) - 2;
- MinSweep := Trunc(MaxSweep - Depth * SampleRate / 1000);
- if (MinSweep < 0) then MinSweep := 0;
- LongRec(Sweep).Hi := (MinSweep + MaxSweep) div 2;
- LongRec(Sweep).Lo := 0;
- end;
- end;
- end;
- {========================================================================}
- function DoFlanger(pfc: PFlanger; Buf: PChar; Len: Longint): Boolean;
- const
- ifac = 65536;
- var
- pW: PSmallInt;
- pB: PByte;
- mask: integer;
- inval,outval: Longint;
- begin
- Result := False;
- if (pfc <> nil) then
- with pfc^ do
- begin
- mask := DLineSize-1;
- if (DataType and DT_STEREO = DT_STEREO) then { stereo }
- begin
- if (DataType and DT_16BIT = DT_16BIT) then { 16-bit }
- begin
- pW := PSmallInt(Buf);
- while (Len > 0) do
- begin
- { interpolate from the 2 read values }
- outval := (DLineL^[ep1]*LongRec(Sweep).Lo+
- DLineL^[ep2]*(ifac-LongRec(Sweep).Lo))div ifac;
- { store finished input plus feedback }
- inval := pW^ + sar(outval * Feedback,8);
- if (inval > 32767) then
- begin
- inval := 32767;
- Result := True;
- end
- else if (inval < -32768) then
- begin
- inval := -32768;
- Result := True;
- end;
- DLineL^[DLinePos] := inval;
- { develop final output mix }
- outval := sar(outval*WetMix,8) + sar(inval*DryMix,8);
- if (outval > 32767) then
- begin
- outval := 32767;
- Result := True;
- end
- else if (outval < -32768) then
- begin
- outval := -32768;
- Result := True;
- end;
- pW^ := outval;
- inc(pW);
- { right channel }
- { interpolate from the 2 read values }
- outval := (DLineR^[ep1]*LongRec(Sweep).Lo+
- DLineR^[ep2]*(ifac-LongRec(Sweep).Lo))div ifac;
- { store finished input plus feedback }
- inval := pW^ + sar(outval * Feedback,8);
- if (inval > 32767) then
- begin
- inval := 32767;
- Result := True;
- end
- else if (inval < -32767) then
- begin
- inval := -32767;
- Result := True;
- end;
- DLineR^[DLinePos] := inval;
- { develop final output mix }
- outval := sar(outval*WetMix,8) + sar(inval*DryMix,8);
- if (outval > 32767) then
- begin
- outval := 32767;
- Result := True;
- end
- else if (outval < -32767) then
- begin
- outval := -32767;
- Result := True;
- end;
- pW^ := outval;
- inc(pW);
- { update ptrs }
- DLinePos := (DLinePos + 1) and mask;
- sweep := sweep + step;
- ep1 := (DLinePos + LongRec(Sweep).Hi) and mask;
- ep2 := (ep1 - 1) and mask;
- { check for sweep reversal }
- if (LongRec(Sweep).Hi > MaxSweep) or { see if we hit top of sweep }
- (LongRec(Sweep).Hi < MinSweep) then { or if we hit bottom of sweep }
- Step := -Step; { reverse }
- dec(Len,2*sizeOf(SmallInt));
- end;
- end
- else { 8 bit }
- begin
- pB := PByte(Buf);
- while (Len > 0) do
- begin
- { left channel }
- { interpolate from the 2 read values }
- outval := (DLineL^[ep1]*LongRec(Sweep).Lo+
- DLineL^[ep2]*(ifac-LongRec(Sweep).Lo))div ifac;
- { store finished input plus feedback }
- inval := (pB^-128)shl 8 + sar(outval * Feedback,8);
- if (inval > 32767) then
- begin
- inval := 32767;
- Result := True;
- end
- else if (inval < -32767) then
- begin
- inval := -32767;
- Result := True;
- end;
- DLineL^[DLinePos] := inval;
- { develop final output mix }
- outval := sar(outval*WetMix,8) + sar(inval*DryMix,8);
- if (outval > 32767) then
- begin
- outval := 32767;
- Result := True;
- end
- else if (outval < -32768) then
- begin
- outval := -32768;
- Result := True;
- end;
- pB^ := (outval shr 8)+128;
- inc(pB);
- { right channel }
- { interpolate from the 2 read values }
- outval := (DLineR^[ep1]*LongRec(Sweep).Lo+
- DLineR^[ep2]*(ifac-LongRec(Sweep).Lo))div ifac;
- { store finished input plus feedback }
- inval := (pB^-128) shl 8 + sar(outval * Feedback,8);
- if (inval > 32767) then
- begin
- inval := 32767;
- Result := True;
- end
- else if (inval < -32767) then
- begin
- inval := -32767;
- Result := True;
- end;
- DLineR^[DLinePos] := inval;
- { develop final output mix }
- outval := sar(outval*WetMix,8) + sar(inval*DryMix,8);
- if (outval > 32767) then
- begin
- outval := 32767;
- Result := True;
- end
- else if (outval < -32768) then
- begin
- outval := -32768;
- Result := True;
- end;
- pB^ := (outval shr 8)+128;
- inc(pB);
- { update ptrs }
- DLinePos := (DLinePos + 1) and mask;
- sweep := sweep + step;
- ep1 := (DLinePos + LongRec(Sweep).Hi) and mask;
- ep2 := (ep1 - 1) and mask;
- { check for sweep reversal }
- if (LongRec(Sweep).Hi > MaxSweep) or { see if we hit top of sweep }
- (LongRec(Sweep).Hi < MinSweep) then { or if we hit bottom of sweep }
- Step := -Step; { reverse }
- dec(Len,2*sizeOf(Byte));
- end;
- end;
- end
- else { mono }
- begin
- if (DataType and DT_16BIT = DT_16BIT) then { 16-bit }
- begin
- pW := PSmallInt(Buf);
- while (Len > 0) do
- begin
- { interpolate from the 2 read values }
- outval := (DLineL^[ep1]*LongRec(Sweep).Lo+
- DLineL^[ep2]*(ifac-LongRec(Sweep).Lo))div ifac;
- { store finished input plus feedback }
- inval := pW^ + sar(outval*Feedback,8);
- if (inval > 32767) then
- begin
- inval := 32767;
- Result := True;
- end
- else if (inval < -32767) then
- begin
- inval := -32767;
- Result := True;
- end;
- DLineL^[DLinePos] := inval;
- { develop final output mix }
- outval := sar(outval*WetMix,8) + sar(inval*DryMix,8);
- if (outval > 32767) then
- begin
- outval := 32767;
- Result := True;
- end
- else if (outval < -32768) then
- begin
- outval := -32768;
- Result := True;
- end;
- pW^ := outval;
- inc(pW);
- { update ptrs }
- DLinePos := (DLinePos + 1) and mask;
- sweep := sweep + step;
- ep1 := (DLinePos + LongRec(Sweep).Hi) and mask;
- ep2 := (ep1 - 1) and mask;
- { check for sweep reversal }
- if (LongRec(Sweep).Hi > MaxSweep) or { see if we hit top of sweep }
- (LongRec(Sweep).Hi < MinSweep) then { or if we hit bottom of sweep }
- Step := -Step; { reverse }
- dec(Len,sizeOf(SmallInt));
- end;
- end
- else
- begin { 8 Bit }
- pB := PByte(Buf);
- while (Len > 0) do
- begin
- { interpolate from the 2 read values }
- outval := (DLineL^[ep1]*LongRec(Sweep).Lo+
- DLineL^[ep2]*(ifac-LongRec(Sweep).Lo))div ifac;
- { store finished input plus feedback }
- inval := (pB^-128)shl 8 + sar(outval*Feedback,8);
- if (inval > 32767) then
- begin
- inval := 32767;
- Result := True;
- end
- else if (inval < -32767) then
- begin
- inval := -32767;
- Result := True;
- end;
- DLineL^[DLinePos] := inval;
- { develop final output mix }
- outval := sar(outval*WetMix,8) + sar(inval*DryMix,8);
- if (outval > 32767) then
- begin
- outval := 32767;
- Result := True;
- end
- else if (outval < -32768) then
- begin
- outval := -32768;
- Result := True;
- end;
- pB^ := (outval shr 8)+128;
- inc(pB);
- { update ptrs }
- DLinePos := (DLinePos + 1) and mask;
- sweep := sweep + step;
- ep1 := (DLinePos + LongRec(Sweep).Hi) and mask;
- ep2 := (ep1 - 1) and mask;
- { check for sweep reversal }
- if (LongRec(Sweep).Hi > MaxSweep) or { see if we hit top of sweep }
- (LongRec(Sweep).Hi < MinSweep) then { or if we hit bottom of sweep }
- Step := -Step; { reverse }
- dec(Len,sizeOf(Byte));
- end;
- end;
- end;
- end;
- end;
- {========================================================================}
- { -- PitchChange -- }
- {========================================================================}
- function InitPitchChange(pwfx: PWaveFormatEx; MaxDelay: integer): PPitchChange;
- var
- i: integer;
- begin
- Result := GlobalAllocMem(SizeOf(TPitchChange));
- if (Result <> nil) then
- begin
- {$IFNDEF USEASM}
- MaxDelay := Min(MaxDelay,500);
- {$ENDIF}
- Result^.MaxDelay := MaxDelay;
- with Result^ do
- begin
- DataType := GetDataType(pwfx);
- SampleRate := pwfx^.nSamplesPerSec;
- Delay := 0;
- DLineL := nil;
- DLineR := nil;
- { Calculate delay line size }
- DLineSize := MulDiv32(SampleRate,MaxDelay,1000);
- i := 0;
- while DLineSize > 2048 do
- begin
- DLineSize := DLineSize shr 1;
- inc(i);
- end;
- DLineSize := 2048;
- while i > 0 do
- begin
- DLineSize := DLineSize shl 1;
- dec(i);
- end;
- DLineSize := 4096;
- DLineL := GlobalAllocMem(sizeOf(Longint)*DLineSize);
- if (DataType and DT_STEREO = DT_STEREO) then
- DLineR := GlobalAllocMem(sizeOf(Longint)*DLineSize);
- if (DLineL = nil) or
- ((DLineR = nil) and (DataType and DT_STEREO = DT_STEREO)) then
- begin
- DonePitchChange(Result);
- end;
- end;
- end;
- end;
- {========================================================================}
- procedure DonePitchChange(var ppc: PPitchChange);
- begin
- if (ppc <> nil) then
- begin
- GlobalFreeMem(Pointer(ppc^.DLineL));
- GlobalFreeMem(Pointer(ppc^.DLineR));
- GlobalFreeMem(Pointer(ppc));
- end;
- end;
- {========================================================================}
- procedure SetPitchChange(ppc: PPitchChange; iDry,iWet,iFeedBack,
- iDelay,iDepth: Longint; iRate: Float);
- var
- i: integer;
- begin
- if (ppc <> nil) then
- begin
- with ppc^ do
- begin
- FeedBack:= iFeedBack * 256 div 100;
- DryMix := iDry * 256 div 100;
- WetMix := iWet * 256 div 100;
- Rate := iRate;
- Depth := iDepth; //???????
- Step := Trunc(iRate * 65535.0);
- Delay := Min(iDelay,MaxDelay); //????
- if (DLineSize > 0) then
- begin
- FillChar(DLineL^,sizeOf(Longint)*DLineSize,0);{ Clear delay lines }
- if (DataType and DT_STEREO = DT_STEREO) then
- FillChar(DLineR^,sizeOf(Longint)*DLineSize,0);
- end;
- // fetch params
- SweepUp := True {Rate > 0};
- XFade := Min(12 * SampleRate div 1000,MAX_XTAB);
- // init/calc some stuff
- MaxSweep := DLineSize - 2 - MulDiv32(SampleRate,Delay,1000);
- MinSweep := Max(MaxSweep - MulDiv32(SampleRate,Depth,1000),0);
- Active := Trunc(MaxSweep - MinSweep - (XFade * Rate) - 2);
- { build the crossfade lookup tables }
- for i := 0 to XFade-1 do
- begin
- Fade_In[i] := cos(i * M2_PI / XFade);
- Fade_Out[i]:= sin(i * M2_PI / XFade);
- end;
- // init store and read ptrs to known value, chanA active 1st
- fp := 0;
- ep3 := 0;
- ep4 := 0;
- XFadeCnt := 0;
- Sweep := 0;
- if SweepUp then
- begin
- ep1 := MinSweep;
- ep2 := MinSweep;
- end
- else
- begin
- ep1 := MaxSweep;
- ep2 := MaxSweep;
- end;
- ActiveCnt := Active;
- BlendA := 1.0;
- BlendB := 0.0;
- FadeA := @Fade_Out;
- FadeB := @Fade_In;
- ChanA := True;
- end;
- end;
- end;
- {========================================================================}
- procedure DoPitchChange(ppc: PPitchChange; Buffer: PChar; Len: Longint);
- Label Next;
- const
- ifac = 65536.0;
- var
- pW: PSmallInt;
- mask: integer;
- Inval,Outval: Longint;
- comp: Float;
- // macros for pitch_change delay index manipulation
- procedure inc_index(var x: integer);
- begin
- x := (x + 1) and mask;
- end;
- procedure inc_indexes(var x1,x2: integer);
- begin
- x2 := x1;
- inc_index(x1);
- end;
- begin
- if (ppc <> nil) then
- with ppc^ do
- begin
- mask := DLineSize-1;
- { mono }
- if (DataType and DT_16BIT = DT_16BIT) then { 16-bit }
- begin
- pW := PSmallInt(Buffer);
- while (Len > 0) do
- begin
- // messy expression to interpolate from both pairs of read ptrs
- comp := ifac - Sweep;
- Outval := Trunc(((DLineL^[ep1] * LongRec(Sweep).Lo + DLineL^[ep2] * comp) * BlendA +
- (DLineL^[ep3] * LongRec(Sweep).Lo + DLineL^[ep4] * comp) * BlendB)
- / ifac);
- // store finished input plus feedback
- inval := pW^ + sar(Outval*Feedback,8);
- DLineL^[fp] := inval;
- { develop final output mix }
- Outval := sar(Outval*WetMix,8) + sar(Inval*DryMix,8);
- if (Outval > 32767) then pW^ := 32767
- else if (Outval < -32767) then pW^ := -32767
- else pW^ := Outval;
- // see if crossfade active
- if (XFadeCnt > 0) then
- begin
- dec(XFadeCnt);
- BlendA := FadeA[XFadeCnt];
- BlendB := FadeB[XFadeCnt];
- end;
- // update store ptr
- inc_index(fp);
- // see which direction
- if SweepUp then
- begin
- // update sweep
- Sweep := Sweep + Word(Step);
- // always inc at least once
- inc_indexes(ep1,ep2);
- inc_indexes(ep3,ep4);
- // if sweep didn't overflow, we're done
- if (LongRec(sweep).Hi = 0) then goto next;
- // sweep overflowed, inc again
- inc_indexes(ep1,ep2);
- inc_indexes(ep3,ep4);
- LongRec(Sweep).Hi := 0;
- // see if it's time to switch over to other delay channel
- dec(ActiveCnt);
- if (ActiveCnt = 0) then
- begin
- XFadeCnt := XFade; // initiate crossfade
- ActiveCnt := Active; // start counter on new channel
- if (ChanA) then // A has been active, go to B
- begin
- ChanA := False;
- ep3 := (fp + MinSweep) and mask;
- FadeA := @Fade_Out;
- FadeB := @Fade_In;
- end
- else
- begin
- chanA := True;
- ep1 := (fp + MinSweep) and mask;
- FadeB := @Fade_Out;
- FadeA := @Fade_In;
- end;
- end;
- end
- else // do downward sweep
- begin
- Sweep := Sweep + Step; // update sweep
- // if sweep didn't overflow, inc ptrs, that's all
- if (LongRec(Sweep).Hi = 0) then
- begin
- inc_indexes(ep1,ep2);
- inc_indexes(ep3,ep4);
- goto next;
- end;
- // sweep overflowed, check on stuff but skip ptr inc
- LongRec(Sweep).Hi := 0;
- // see if it's time to switch over to other delay channel
- dec(ActiveCnt);
- if (ActiveCnt = 0) then
- begin
- XFadeCnt := XFade;
- ActiveCnt := Active;
- if ChanA then // A has been active, go to B */
- begin
- ChanA := False;
- ep3 := (fp + MaxSweep) and mask;
- FadeA := @Fade_Out;
- FadeB := @Fade_In;
- end
- else
- begin
- ChanA := True;
- ep1 := (fp + MaxSweep) and mask;
- FadeB := @Fade_Out;
- FadeA := @Fade_In;
- end;
- end;
- end;
- Next:
- inc(pW);
- dec(Len,sizeOf(SmallInt));
- end;
- end;
- end;
- end;
- end.
- function ReadWaveBuffer( HWND hwnd /*void*/ )
- { //int far *temp;
- static start=0,
- shag=-1,
- ff_shift=10;
- extern f_shift,Flanger,Equalizer,Reverb;
- static Flang_buf[260];}
- begin
- if (start = 0) then
- begin
- //init_imp(256,8,2,50);
- start := 1;
- end;
- // if we haven't encountered the end of the wave yet,
- // read another buffer in...
- if( dwBytedatasize < dwTotalwavesize-45 ) then
- begin
- // read wave chunk from the temporary file...
- //pwavehdr[bufindex]->dwBufferLength = _lread( htmpfile, pwavemem[bufindex], WaveBufSize );
- pwavehdr[bufindex]^.dwBufferLength := _lread(htmpfile, inp_buf, WaveBufSize);
- temp := pwavemem[bufindex];
- //---------------- ! FFT filtr -----------------
- if (Equalizer = 1) then
- begin
- fft_filter(256, 8, 40)
- end
- else
- begin
- for i := 0 to (256*40)-1 do
- begin
- inp_buf[i] := inp_buf[i] shr 1;
- end;
- end;
- //if( Reverb == 1 ){ ReverB();}
- //_fmemcpy(&temp[256*40],inp_buf,256*80 );
- //f_shift = 400;shag=-1;
- if (Chorus = 0) then
- begin
- if (Flanger = 0) then
- begin
- for i := 0 to (256*40)-1 do
- begin
- temp[i*2] := inp_buf[i];
- temp[i*2+1] := inp_buf[i];
- end;
- end
- else
- begin
- //---------------------- FLANGER ---------------------------
- for i := 0 to (256*40)-1 do
- begin
- if (i mod 90 = 0) then
- begin
- ff_shift := ff_shift + shag;
- if (ff_shift > 250) then shag := -1;
- if (ff_shift < 50) then shag := 1;
- end;
- //----------------------------------------------------------
- if(i < ff_shift) then
- begin
- temp[_i*2+1]=temp[_i*2]=((long)((long)flang_buf[1000-ff_shift+_i] +(long)inp_buf[_i])>>1);
- end
- else
- begin
- temp[_i*2+1]=temp[_i*2]=((long)((long)inp_buf[_i-ff_shift] + (long)inp_buf[_i])>>1);
- end;
- //if(_i>=10240-1900){ flang_buf[1900-10240+_i]=inp_buf[_i];}
- end;
- _fmemcpy(&flang_buf[0],&inp_buf[10240-1000],1000*2 );
- end;
- end
- else //---- stereo chorus ON ---------------------------
- begin
- //---------------------- FLANGER ---------------------------
- if (Flanger = 1) or (Flanger = 2) then
- begin
- _fmemcpy(temp,inp_buf,256*80);
- if (Flanger = 1) then
- begin
- for (i := 0 to (256*40)-1 do
- begin
- if (i mod 90 = 0) then
- begin
- ff_shift := ff_shift + shag;
- if (ff_shift > 250) then shag := -1;
- if (ff_shift < 25) then shag :=1;
- end;
- if (i < ff_shift) then
- begin
- inp_buf[_i]= ((long)Flang_buf[259-ff_shift+_i]+(long)temp[_i])>>0;
- end
- else
- begin
- inp_buf[_i]=((long)temp[_i-ff_shift]+(long)temp[_i])>>0; }
- end;
- end;
- end
- else
- begin
- for i := 0 to (256*40)-1 do
- begin
- if (i mod 60 = 0) then
- begin
- ff_shift := ff_shift + shag;
- if (ff_shift > 250) then shag := -1;
- if (ff_shift < 50) then shag :=1;
- end;
- if (i < ff_shift) then
- begin
- inp_buf[_i]= ((long)Flang_buf[259-ff_shift+_i]+(long)temp[_i])>>0;
- end
- else
- begin
- inp_buf[_i]=((long)temp[_i-ff_shift]+(long)temp[_i])>>0;
- end;
- end;
- end;
- _fmemcpy(&Flang_buf[0],&temp[10240-259],259*2 );
- end;
- //for(_i=0;_i<256*40;_i++){ temp[_i*2]=temp[_i*2+1]=inp_buf[_i];}
- //------------------------------- CHORUS -------
- for i := 0 to (256*40)-1 do
- begin
- temp[i*2+1] := inp_buf[i];
- if (i < f_shift) then
- begin
- temp[i*2] := flang_buf[1000-f_shift+i];
- end
- else
- begin
- temp[i*2]=inp_buf[i-f_shift]; }
- end;
- //for(_i=0;_i<256*40;_i++)
- {
- //if(_i>=10240-1900){ flang_buf[1900-10240+_i]=inp_buf[_i];}
- }
- _fmemcpy(&flang_buf[0],&inp_buf[10240-1000],1000*2 );
- end;
- //if( Reverb == 1 ){ ReverB1(179,127,151); ReverB2(199,107,139);}
- //if( Reverb == 2 ){ ReverB1(757,523,617); ReverB2(787,503,643);}
- if (Reverb = 1) then
- begin
- ReverB1(179, 127,151,111,251);
- ReverB2(199,107,139,117,257);
- end;
- if (Reverb = 2) then
- begin
- ReverB1(1003,761,523,397,401);
- ReverB2(997,769,541,393,239);
- end;
- if (Reverb = 3) then
- begin
- ReverB1(2203,1511,1049,787,241);
- ReverB2(2179,1523,1061,773,251);
- end;
- // update total number of bytes read so far...
- dwBytedatasize += (pwavehdr[bufindex]->dwBufferLength);
- //-!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
- pwavehdr[bufindex]->dwBufferLength *=2L;
- }
- else
- {
- //mmtime.u.cb = 0;
- dwBytedatasize = 0;
- UpdateLength( hwnd, 0, 0 );
- lseek( htmpfile, 44L, SEEK_SET );
- // read wave chunk from the temporary file...
- //pwavehdr[bufindex]->dwBufferLength = _lread( htmpfile, pwavemem[bufindex], WaveBufSize );
- pwavehdr[bufindex]->dwBufferLength = 0;
- // update total number of bytes read so far...
- dwBytedatasize += pwavehdr[bufindex]->dwBufferLength;
- /*----------- OLD Version ---------------------*/
- // otherwise the last buffer has been queued, just let it finish playing...
- //MoreBuffers = OFF; // handled in MM_WOM_DONE in MainWndProc()
- //return 1;
- /*---------- END Old Version ------------------*/
- }
- return 0;
- }
- end.
- *)
- (*
- -------------------------------------------------------------------------
- 3.4 Distortion
- --------------
- Now its time to get some sound output. Connect an amplifier or speaker to
- the speaker/headphone connector of the SGPRO16 card. Select the Distortion
- option and set the level to 0. The only thing the program does is reading
- ADC sample values and feeding them to the DAC, without altering them at
- all. You should now hear the sound you input to the card. If it is
- distorted there are two possible causes: if the input level is too high,
- adjust your instrument volume, or decrease the input gain entry in the
- configuration file. If the output level is too high, adjust it with the
- volume control on your card, or decrease the DAC attenuation entry in the
- configuration file.
- My machine is not fast enough to run this algorithm at 48 kHz. At 48 kHz
- clicks are audible, because the program is sometimes too late to read a
- sample from the ADC. The highest sample rate that doesn't cause this
- problem is 32 kHz. If you have a very slow machine, the number of samples
- it misses is so large that it causes the sound to be distorted quite
- heavily.
- Setting the distortion level to a level higher than 0 will create a
- distorted sound. I use quite a naive algorithm. For a certain distortion
- level (Level) the value input to the DAC (In) is related to the ADC output
- (Out) by:
- (1 - Level/10)
- ( abs(In) )
- Out = 32767 * sign(In) * ( ------- )
- ( 32767 )
- processed_buf[i] = 32767*sign(in)*(abs(in)/32767)^(1-level/10);
-
- Both In and Out are signed 16-bit integers. The use of this function also
- compresses the signal: small volume signals are amplified more than large
- ones.
- *)
- (* Values for reverb
- { Hall Reverb
- ------------ }
- {FeedBack := 30;
- NumReverbs := 5;
- Reverb[0].Delay := 100;
- Reverb[0].Gain := -15;
- Reverb[1].Delay := 120;
- Reverb[1].Gain := 30;
- Reverb[2].Delay := 140;
- Reverb[2].Gain := -35;
- Reverb[3].Delay := 175;
- Reverb[3].Gain := 30;
- Reverb[4].Delay := 200;
- Reverb[4].Gain := 20;}
- { Room Reverb
- ------------ }
- {FeedBack := 35;
- NumReverbs := 4;
- Reverb[0].Delay := 5;
- Reverb[0].Gain := 20;
- Reverb[1].Delay := 20;
- Reverb[1].Gain := -30;
- Reverb[2].Delay := 30;
- Reverb[2].Gain := -20;
- Reverb[3].Delay := 40;
- Reverb[3].Gain := 40;}
- { Hall Reverb Big
- ---------------- }
- { FeedBack := 86;
- NumReverbs := 5;
- Reverb[0].Delay := 42;
- Reverb[0].Gain := 16;
- Reverb[1].Delay := 79;
- Reverb[1].Gain := -19;
- Reverb[2].Delay := 107;
- Reverb[2].Gain := 24;
- Reverb[3].Delay := 157;
- Reverb[3].Gain := -27;
- Reverb[4].Delay := 163;
- Reverb[4].Gain := -28;}
- { Metallic Reverb
- ---------------- }
- { FeedBack := 60;
- NumReverbs := 4;
- Reverb[0].Delay := 30;
- Reverb[0].Gain := 30;
- Reverb[1].Delay := 40;
- Reverb[1].Gain := -25;
- Reverb[2].Delay := 50;
- Reverb[2].Gain := 25;
- Reverb[3].Delay := 80;
- Reverb[3].Gain := 25; }
- { Air Duct Reverb
- ----------------- }
- { FeedBack := 60;
- NumReverbs := 4;
- Reverb[0].Delay := 20;
- Reverb[0].Gain := 18;
- Reverb[1].Delay := 40;
- Reverb[1].Gain := -48;
- Reverb[2].Delay := 50;
- Reverb[2].Gain := 58;
- Reverb[3].Delay := 90;
- Reverb[3].Gain := 13;}
- { Distance Echo
- --------------- }
- { FeedBack := 75;
- NumReverbs := 2;
- Reverb[0].Delay := 160;
- Reverb[0].Gain := 30;
- Reverb[1].Delay := 300;
- Reverb[1].Gain := 50;}
- { Bass Bost
- ----------- }
- { FeedBack := 0;
- NumReverbs := 1;
- Reverb[0].Delay := 0;
- Reverb[0].Gain := 60;}
- { Heavy Bass Boost
- ----------------- }
- { FeedBack := -10;
- NumReverbs := 1;
- Reverb[0].Delay := 0;
- Reverb[0].Gain := 150;}
- { Cathedral 1
- ------------ }
- {FeedBack := -47;
- NumReverbs := 5;
- Reverb[0].Delay := 100;
- Reverb[0].Gain := 16;
- Reverb[1].Delay := 150;
- Reverb[1].Gain := -20;
- Reverb[2].Delay := 200;
- Reverb[2].Gain := 36;
- Reverb[3].Delay := 250;
- Reverb[3].Gain := -20;
- Reverb[4].Delay := 300;
- Reverb[4].Gain := -24; }
- { Cathedral 2
- ------------ }
- {FeedBack := 24;
- NumReverbs := 8;
- Reverb[0].Delay := 100;
- Reverb[0].Gain := 17;
- Reverb[1].Delay := 150;
- Reverb[1].Gain := -24;
- Reverb[2].Delay := 200;
- Reverb[2].Gain := 27;
- Reverb[3].Delay := 250;
- Reverb[3].Gain := -20;
- Reverb[4].Delay := 300;
- Reverb[4].Gain := -24;
- Reverb[5].Delay := 400;
- Reverb[5].Gain := 16;
- Reverb[6].Delay := 500;
- Reverb[6].Gain := -13;
- Reverb[7].Delay := 700;
- Reverb[7].Gain := 6;}
- { Very Big Hall
- -------------- }
- { FeedBack := 40;
- NumReverbs := 5;
- Reverb[0].Delay := 20;
- Reverb[0].Gain := 42;
- Reverb[1].Delay := 20;
- Reverb[1].Gain := -36;
- Reverb[2].Delay := 49;
- Reverb[2].Gain := 31;
- Reverb[3].Delay := 160;
- Reverb[3].Gain := 34;
- Reverb[4].Delay := 980;
- Reverb[4].Gain := 16;}
- { Reverb 1
- --------- }
- { FeedBack := 13;
- NumReverbs := 3;
- Reverb[0].Delay := 50;
- Reverb[0].Gain := -70;
- Reverb[1].Delay := 75;
- Reverb[1].Gain := 31;
- Reverb[2].Delay := 100;
- Reverb[2].Gain := 40;}
- { Reverb 2
- --------- }
- { FeedBack := -16;
- NumReverbs := 5;
- Reverb[0].Delay := 50;
- Reverb[0].Gain := -70;
- Reverb[1].Delay := 75;
- Reverb[1].Gain := 31;
- Reverb[2].Delay := 100;
- Reverb[2].Gain := 40;
- Reverb[3].Delay := 25;
- Reverb[3].Gain := 13;
- Reverb[4].Delay := 90;
- Reverb[4].Gain := -16;}
- { Hagel
- ------ }
- {FeedBack := 31;
- NumReverbs := 8;
- Reverb[0].Delay := 50;
- Reverb[0].Gain := 20;
- Reverb[1].Delay := 70;
- Reverb[1].Gain := -8;
- Reverb[2].Delay := 100;
- Reverb[2].Gain := 14;
- Reverb[3].Delay := 120;
- Reverb[3].Gain := -6;
- Reverb[4].Delay := 140;
- Reverb[4].Gain := 22;
- Reverb[5].Delay := 150;
- Reverb[5].Gain := -5;
- Reverb[6].Delay := 160;
- Reverb[6].Gain := 16;
- Reverb[7].Delay := 170;
- Reverb[7].Gain := -2;}
- { Big Room
- ---------- }
- { FeedBack := 16;
- NumReverbs := 8;
- Reverb[0].Delay := 40;
- Reverb[0].Gain := -17;
- Reverb[1].Delay := 60;
- Reverb[1].Gain := 8;
- Reverb[2].Delay := 100;
- Reverb[2].Gain := 3;
- Reverb[3].Delay := 120;
- Reverb[3].Gain := 0;
- Reverb[4].Delay := 140;
- Reverb[4].Gain := 33;
- Reverb[5].Delay := 150;
- Reverb[5].Gain := 0;
- Reverb[6].Delay := 160;
- Reverb[6].Gain := 27;
- Reverb[7].Delay := 170;
- Reverb[7].Gain := 31; }
- { Simple Echo
- ------------ }
- {FeedBack := 0;
- NumReverbs := 1;
- Reverb[0].Delay := 150;
- Reverb[0].Gain := 63;}
- { Long Echo
- ---------- }
- { FeedBack := 50;
- NumReverbs := 1;
- Reverb[0].Delay := 350;
- Reverb[0].Gain := -50; }
- { Alpia Echo
- ----------- }
- { FeedBack := 0;
- NumReverbs := 1;
- Reverb[0].Delay := 750;
- Reverb[0].Gain := 62; }
- { Double Echo
- ------------ }
- { FeedBack := 0;
- NumReverbs := 2;
- Reverb[0].Delay := 100;
- Reverb[0].Gain := -62;
- Reverb[1].Delay := 200;
- Reverb[1].Gain := 31; }
- { Alien 1
- -------- }
- { FeedBack := 47;
- NumReverbs := 3;
- Reverb[0].Delay := 10;
- Reverb[0].Gain := 47;
- Reverb[1].Delay := 28;
- Reverb[1].Gain := -27;
- Reverb[2].Delay := 55;
- Reverb[2].Gain := 42; }
- { Alien 2
- -------- }
- {FeedBack := 47;
- NumReverbs := 5;
- Reverb[0].Delay := 10;
- Reverb[0].Gain := 47;
- Reverb[1].Delay := 28;
- Reverb[1].Gain := -27;
- Reverb[2].Delay := 55;
- Reverb[2].Gain := 42;
- Reverb[3].Delay := 14;
- Reverb[3].Gain := 47;
- Reverb[4].Delay := 12;
- Reverb[4].Gain := 16; }
- { Strange FeedBack 1
- ------------------- }
- {FeedBack := 63;
- NumReverbs := 2;
- Reverb[0].Delay := 10;
- Reverb[0].Gain := -66;
- Reverb[1].Delay := 11;
- Reverb[1].Gain := 75;}
- { Strange FeedBack 2
- ------------------- }
- { FeedBack := 55;
- NumReverbs := 3;
- Reverb[0].Delay := 10;
- Reverb[0].Gain := -56;
- Reverb[1].Delay := 11;
- Reverb[1].Gain := 63;
- Reverb[2].Delay := 12;
- Reverb[2].Gain := -40;}
- { Strange FeedBack 3
- ------------------- }
- { FeedBack := 62;
- NumReverbs := 2;
- Reverb[0].Delay := 15;
- Reverb[0].Gain := -66;
- Reverb[1].Delay := 16;
- Reverb[1].Gain := 64; }
- { FeedBack Overload
- ------------------ }
- { FeedBack := 78;
- NumReverbs := 4;
- Reverb[0].Delay := 100;
- Reverb[0].Gain := 39;
- Reverb[1].Delay := 150;
- Reverb[1].Gain := -31;
- Reverb[2].Delay := 200;
- Reverb[2].Gain := 42;
- Reverb[3].Delay := 250;
- Reverb[3].Gain := -23;}
- // SetReverb(prvb, False, 90, 0, 100, FeedBack, NumReverbs, @Reverb);
- *)
- (*
- // SetPhaser(pph,50,CH_LEFT);
- // Dry Wet FB Sweep Depth, Rate,
- // SetPhaseShift(pps, 70, 70, 0, 100, 4, 1); // Phase shift
- // SetPhaseShift(pps, 99, -99, -60, 100, 6, 0.2); // Slow invert phase shift w FB
- // Dry Wet FB Delay Depth, Rate,
- // SetFlanger(pfc, 50, 50, 70, 250, 0, 0.0); // Echoes
- SetFlanger(pfc, 50, 50, 0, 0, 6, 2.0); // Slow Flange
- // SetFlanger(pfc, 50,-50,-70, 0, 6, 2.0); // Slow invert flange w FB
- // SetFlanger(pfc, 50, 50, 0, 20, 20, 11.0); // Slow Chorus
- *)