MMPCMSup.pas
上传用户:hylc_2004
上传日期:2014-01-23
资源大小:46800k
文件大小:62k
- {========================================================================}
- {= (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/index.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: 12.11.98 - 20:57:03 $ =}
- {========================================================================}
- unit MMPCMSup;
- {$I COMPILER.INC}
- interface
- uses
- {$IFDEF WIN32}
- Windows,
- {$ELSE}
- WinTypes,
- WinProcs,
- {$ENDIF}
- SysUtils,
- Forms,
- MMSystem,
- MMUtils,
- MMMath,
- MMRegs,
- MMWaveIO,
- MMAbout;
- type
- {$IFDEF WIN32}
- TDataSize = Longint;
- {$ELSE}
- {$IFDEF USEASM}
- TDataSize = Longint;
- {$ELSE}
- TDataSize = integer;
- {$ENDIF}
- {$ENDIF}
- const
- Overflow : Boolean = False;
- type
- PMMMixPool = ^TMMMixPool;
- TMMMixPool = record
- dwLeftVolume : Longint; { master volumes }
- dwRightVolume: Longint;
- lpBuffers : array[0..0] of PChar;
- end;
- {------------------------------------------------------------------------}
- function pcmSampleClip8(Sample: Smallint): Shortint;
- function pcmSampleClip16(Sample: Longint): Smallint;
- {------------------------------------------------------------------------}
- function pcmSampleVolume8(Sample: ShortInt; Volume: Longint): Shortint;
- function pcmSampleVolume16(Sample: Smallint; Volume: Longint): Smallint;
- {------------------------------------------------------------------------}
- function pcmVolume(pwfx: PWaveFormatEx; lpData: PChar; dwSrcLen: TDataSize;
- LeftVolume, RightVolume: Longint): Boolean;
- function pcmVolume8M(lpData: PChar; dwSrcLen: TDataSize; Volume: Longint): Boolean;
- {$IFDEF WIN32}pascal;{$ENDIF}
- function pcmVolume8S(lpData: PChar; dwSrcLen: TDataSize;
- LeftVolume, RightVolume: Longint): Boolean;
- {$IFDEF WIN32}pascal;{$ENDIF}
- function pcmVolume16M(lpData: PChar; dwSrcLen: TDataSize; Volume: Longint): Boolean;
- {$IFDEF WIN32}pascal;{$ENDIF}
- function pcmVolume16S(lpData: PChar; dwSrcLen: TDataSize;
- LeftVolume, RightVolume: Longint): Boolean;
- {$IFDEF WIN32}pascal;{$ENDIF}
- {------------------------------------------------------------------------}
- procedure pcmReverse(pwfx: PWaveFormatEx; lpData: PChar; dwSrcLen: TDataSize);
- {------------------------------------------------------------------------}
- function pcmPitchChange(pwfx: PWaveFormatEx; pSrc,pDst: PChar;
- var SrcLen,DstLen,IncValue: Longint; Factor: Longint): Longint;
- function pcmPitchChange8M(pSrc,pDst: PChar; var SrcLen,DstLen,IncValue: Longint;
- Factor: Longint): Longint; {$IFDEF WIN32}pascal;{$ENDIF}
- function pcmPitchChange8S(pSrc,pDst: PChar; var SrcLen,DstLen,IncValue: Longint;
- Factor: Longint): Longint; {$IFDEF WIN32}pascal;{$ENDIF}
- function pcmPitchChange16M(pSrc,pDst: PChar; var SrcLen,DstLen,IncValue: Longint;
- Factor: Longint): Longint; {$IFDEF WIN32}pascal;{$ENDIF}
- function pcmPitchChange16S(pSrc,pDst: PChar; var SrcLen,DstLen,IncValue: Longint;
- Factor: Longint): Longint; {$IFDEF WIN32}pascal;{$ENDIF}
- {------------------------------------------------------------------------}
- function pcmAllocMixPool(NumTracks: integer): PMMMixPool;
- function pcmMixIt(pwfx: PWaveFormatEx;
- pDst: PChar; pTemp: PChar;
- const pSrc: PMMMixPool; NumWaves: integer;
- dwSrcLen: Longint): Boolean;
- function pcmMixIt8(pDst: PChar; pTemp: PSmallint;
- const pSrc: PMMMixPool; NumWaves: integer;
- dwSrcLen: Longint): Boolean;
- {$IFDEF WIN32}pascal;{$ENDIF}
- function pcmMixIt16(pDst: PChar; pTemp: PLongint;
- const pSrc: PMMMixPool; NumWaves: integer;
- dwSrcLen: Longint): Boolean;
- {$IFDEF WIN32}pascal;{$ENDIF}
- {------------------------------------------------------------------------}
- function pcmIsValidFormat(pwfx: PWaveFormatEx): Boolean;
- procedure pcmBuildWaveHeader(pwfx: PWaveFormatEx;wBitsPS,nChannels: Word;
- dwSampleRate: Longint);
- procedure pcmBuildWaveFormatExtensible(pwfxEx: PWaveFormatExtensible;
- wBitsPS, nChannels: Word;
- dwSampleRate: DWORD;
- dwChannelMask: DWORD);
- procedure pcmFillSilence(pwfx: PWaveFormatEx; lpData: PChar; dwLength: Longint);
- function pcmFindZeroCross(pwfx: PWaveFormatEx; pSrc: PChar; dwSrcLen: Cardinal;
- Channel, Flank, Level: Integer): Longint;
- procedure pcmCalcStatistics(pwfx: PWaveFormatEx; pSrc: PChar; dwSrcLen: TDataSize;
- var AvgL, AvgR, RmsL, RmsR: SmallInt);
- procedure pcmFindPeak(pwfx: PWaveFormatEx; pSrc: PChar; dwSrcLen: TDataSize;
- var PeakL, PeakR: SmallInt); {$IFDEF WIN32}pascal;{$ENDIF}
- procedure pcmFindMinMax(pwfx: PWaveFormatEx; pSrc: PChar; dwSrcLen: TDataSize;
- var MinL, MaxL, MinR, MaxR: SmallInt); {$IFDEF WIN32}pascal;{$ENDIF}
- procedure pcmFindSilenceEnd(pwfx: PWaveFormatEx; pSrc: PChar; dwSrcLen: TDataSize;
- Threshold: Longint; var SilenceEnd: Longint);
- procedure pcmFindSilenceStart(pwfx: PWaveFormatEx; pSrc: PChar; dwSrcLen: TDataSize;
- Threshold: Longint; var SilenceStart: Longint);
- function pcmConvertSizeOutputData(pwfDst, pwfSrc: PPCMWaveFormat;
- NumBytesSrc: Longint): Longint; {$IFDEF WIN32}pascal;{$ENDIF}
- function pcmConvert(pwfDst: PPCMWaveFormat; pDst: PChar;
- pwfSrc: PPCMWaveFormat; pSrc: PChar;
- dwSrcLen: Cardinal): Cardinal; {$IFDEF WIN32}pascal;{$ENDIF}
- function pcmBitsPerSampleAlign(nDstBitsPS: Word; pDst: PChar;
- nSrcBitsPS: Word; pSrc: PChar;
- dwSrcLen: Cardinal): Cardinal;
- function pcmChannelAlign(nDstChannels: Word; pDst: PChar;
- nSrcChannels: Word; pSrc: PChar;
- nBitsPS: Word; dwSrcLen: Cardinal): Cardinal;
- procedure pcmAvgSample8(pDst, pSrc: PChar; nSkip, nChannels: Word);
- procedure pcmAvgSample16(pDst, pSrc: PChar; nSkip, nChannels: Word);
- procedure pcmRepSample8(pDst, pSrc: PChar; nRep, nChannels: Word);
- procedure pcmRepSample16(pDst, pSrc: PChar; nRep, nChannels: Word);
- function pcmSamplesPerSecAlign(nDstSPS: Longint; pDst: PChar;
- nSrcSPS: Longint; pSrc: PChar;
- nBitsPS, nChannels: Word;
- dwSrcLen: Cardinal): Cardinal;
- implementation
- Uses MMMulDiv;
- {*************************************************************************}
- {* the code below provides 'support' routines for building/verifying *}
- {* PCM wave headers *)
- {*************************************************************************}
- function pcmIsValidFormat(pwfx: PWaveFormatEx): Boolean;
- begin
- Result := False;
- if (pwfx = Nil) then exit;
- if (pwfx^.wFormatTag <> WAVE_FORMAT_PCM) then exit;
- if ((pwfx^.wBitsPerSample <> 8) and (pwfx^.wBitsPerSample <> 16)) then exit;
- if ((pwfx^.nChannels <> 1) and (pwfx^.nChannels <> 2)) then exit;
- if ((pwfx^.nSamplesPerSec < 4000) or (pwfx^.nSamplesPerSec > 100000)) then
- exit;
- Result := True;
- end;
- (*************************************************************************)
- procedure pcmBuildWaveHeader(pwfx: PWaveFormatEx; wBitsPS, nChannels: Word;
- dwSampleRate: Longint);
- begin
- { fill in the info for our destination format... }
- pwfx^.wFormatTag := WAVE_FORMAT_PCM;
- pwfx^.nChannels := nChannels;
- pwfx^.nSamplesPerSec := dwSampleRate;
- pwfx^.wBitsPerSample := wBitsPS;
- { set nAvgBytesPerSec and nBlockAlign }
- pwfx^.nBlockAlign := (wBitsPS * nChannels) div 8;
- pwfx^.nAvgBytesPerSec:= pwfx^.nBlockAlign * pwfx^.nSamplesPerSec;
- pwfx^.cbSize := 0;
- end;
- (*************************************************************************)
- procedure pcmBuildWaveFormatExtensible(pwfxEx: PWaveFormatExtensible;
- wBitsPS, nChannels: Word;
- dwSampleRate: DWORD;
- dwChannelMask: DWORD);
- begin
- pwfxEx^.Format.wFormatTag := WAVE_FORMAT_EXTENSIBLE;
- pwfxEx^.Format.nChannels := nChannels;
- pwfxEx^.Format.nSamplesPerSec := dwSampleRate;
- pwfxEx^.Format.wBitsPerSample := wBitsPS;
- pwfxEx^.Format.nBlockAlign := (wBitsPS * nChannels) div 8;
- pwfxEx^.Format.nAvgBytesPerSec := dwSampleRate*pwfxex^.Format.nBlockAlign;
- pwfxEx^.Format.cbSize := sizeof(TWaveFormatExtensible) - sizeof(TWaveFormatEx);
- pwfxEx^.Samples.wValidBitsPerSample := wBitsPS;
- pwfxEx^.dwChannelMask := dwChannelMask;
- pwfxEx^.SubFormat := KSDATAFORMAT_SUBTYPE_PCM;
- end;
- (*************************************************************************)
- procedure pcmFillSilence(pwfx: PWaveFormatEx; lpData: PChar; dwLength: Longint);
- var
- Silence: integer;
- begin
- if (pwfx^.wBitsPerSample = 16) then
- Silence := 0
- else
- Silence := 128;
- GlobalFillMem(lpData^,dwLength,Silence);
- end;
- {*************************************************************************}
- {* find the zero cross point in pSrc: 8/16 bit, mono/stereo *}
- {*************************************************************************}
- {* Channel: 0 = Both, 1 = Left, 2 = Right *}
- {* Flank : 0 = None, 1 = Up, 2 = Down *)
- (* Level : LevelThreshold in % *) *}
- {*************************************************************************}
- function pcmFindZeroCross(pwfx: PWaveFormatEx; pSrc: PChar; dwSrcLen: Cardinal;
- Channel, Flank, Level: Integer): Longint;
- var
- SrcNumBytes: Longint;
- BytePos: Cardinal;
- begin
- Result := -1;
- if (Flank = 0) or (dwSrcLen = 0) then exit;
- if (Flank = 2) then Level := -Level;
- BytePos:= 0;
- if pwfx^.wBitsperSample = 8 then
- begin
- Level := Trunc(Level*127/100)+128;
- if pwfx^.nChannels = 2 then
- begin
- SrcNumBytes := dwSrcLen and not 1;
- while (SrcNumBytes > 4) do
- begin
- case Channel of
- { both channels }
- 0: begin
- { left }
- if (Flank=1)and(PByte(pSrc)^<Level)and(PByte(pSrc+2)^>=Level) then
- begin
- Result := BytePos+2;
- exit;
- end
- else if (Flank=2)and(PByte(pSrc)^>Level)and(PByte(pSrc+2)^<=Level) then
- begin
- Result := BytePos+2;
- exit;
- end;
- { right }
- if (Flank=1)and(PByte(pSrc+1)^<Level)and(PByte(pSrc+3)^>=Level) then
- begin
- Result := BytePos+3;
- exit;
- end
- else if (Flank=2)and(PByte(pSrc+1)^>Level)and(PByte(pSrc+3)^<=Level) then
- begin
- Result := BytePos+3;
- exit;
- end;
- end;
- { the left channel }
- 1: if (Flank=1)and(PByte(pSrc)^<Level)and(PByte(pSrc+2)^>=Level) then
- begin
- Result := BytePos+2;
- exit;
- end
- else if (Flank=2)and(PByte(pSrc)^>Level)and(PByte(pSrc+2)^<=Level) then
- begin
- Result := BytePos+2;
- exit;
- end;
- { the right channel }
- 2: if (Flank=1)and(PByte(pSrc+1)^<Level)and(PByte(pSrc+3)^>=Level) then
- begin
- Result := BytePos+3;
- exit;
- end
- else if (Flank=2)and(PByte(pSrc+1)^>Level)and(PByte(pSrc+3)^<=Level) then
- begin
- Result := BytePos+3;
- exit;
- end;
- end;
- inc(BytePos, 2*sizeOf(Byte));
- inc(pSrc, 2*sizeOf(Byte));
- dec(SrcNumBytes, 2*sizeOf(Byte));
- end;
- end
- else
- begin
- SrcNumBytes := dwSrcLen;
- while (SrcNumBytes > 2) do
- begin
- { we have only one channel }
- if (Flank=1)and(PByte(pSrc)^<Level)and(PByte(pSrc+1)^>=Level) then
- begin
- Result := BytePos+1;
- exit;
- end
- else if (Flank=2)and(PByte(pSrc)^>Level)and(PByte(pSrc+1)^<=Level) then
- begin
- Result := BytePos+1;
- exit;
- end;
- inc(BytePos, sizeOf(Byte));
- inc(pSrc, sizeOf(Byte));
- dec(SrcNumBytes, sizeOf(Byte));
- end;
- end;
- end
- else
- begin
- Level := Level*327;
- if pwfx^.nChannels = 2 then
- begin
- SrcNumBytes := dwSrcLen and not 3;
- while (SrcNumBytes > 8) do
- begin
- case Channel of
- { both channels }
- 0: begin
- { left }
- if (Flank=1)and(PSmallInt(pSrc)^<Level)and(PSmallInt(pSrc+4)^>=Level) then
- begin
- Result := BytePos+4;
- exit;
- end
- else if (Flank=2)and(PSmallInt(pSrc)^>Level)and(PSmallInt(pSrc+4)^<=Level) then
- begin
- Result := BytePos+4;
- exit;
- end;
- { right }
- if (Flank=1)and(PSmallInt(pSrc+4)^<Level)and(PSmallInt(pSrc+8)^>=Level) then
- begin
- Result := BytePos+8;
- exit;
- end
- else if (Flank=2)and(PSmallInt(pSrc+4)^>Level)and(PSmallInt(pSrc+8)^<=Level) then
- begin
- Result := BytePos+8;
- exit;
- end;
- end;
- { the left channel }
- 1: if (Flank=1)and(PSmallInt(pSrc)^<Level)and(PSmallInt(pSrc+4)^>=Level) then
- begin
- Result := BytePos+4;
- exit;
- end
- else if (Flank=2)and(PSmallInt(pSrc)^>Level)and(PSmallInt(pSrc+4)^<=Level) then
- begin
- Result := BytePos+4;
- exit;
- end;
- { the right channel }
- 2: if (Flank=1)and(PSmallInt(pSrc+4)^<Level)and(PSmallInt(pSrc+8)^>=Level) then
- begin
- Result := BytePos+8;
- exit;
- end
- else if (Flank=2)and(PSmallInt(pSrc+4)^>Level)and(PSmallInt(pSrc+8)^<=Level) then
- begin
- Result := BytePos+8;
- exit;
- end;
- end;
- inc(BytePos, 2*sizeOf(SmallInt));
- inc(pSrc, 2*sizeOf(SmallInt));
- dec(SrcNumBytes, 2*sizeOf(SmallInt));
- end;
- end
- else
- begin
- SrcNumBytes := dwSrcLen and not 1;
- while (SrcNumBytes > 4) do
- begin
- { we have only one channel }
- if (Flank=1)and(PSmallInt(pSrc)^<Level)and(PSmallInt(pSrc+2)^>=Level) then
- begin
- Result := BytePos+2;
- exit;
- end
- else if (Flank=2)and(PSmallInt(pSrc)^>Level)and(PSmallInt(pSrc+2)^<=Level) then
- begin
- Result := BytePos+2;
- exit;
- end;
- inc(BytePos, sizeOf(SmallInt));
- inc(pSrc, sizeOf(SmallInt));
- dec(SrcNumBytes, sizeOf(SmallInt));
- end;
- end;
- end;
- end;
- {*************************************************************************}
- { Computes the RMS amplitude in pSrc: 8/16 bit, mono/stereo *}
- {*************************************************************************}
- procedure pcmCalcStatistics(pwfx: PWaveFormatEx; pSrc: PChar; dwSrcLen: TDataSize;
- var AvgL, AvgR, RmsL, RmsR: SmallInt);
- var
- Samples,SrcBytes: Longint;
- SumL, SumR,
- SumL2,SumR2: Extended;
- s: Smallint;
- begin
- SumL := 0;
- SumR := 0;
- SumL2 := 0;
- SumR2 := 0;
- AvgL := 0;
- AvgR := 0;
- RmsL := 0;
- RmsR := 0;
- Samples := 0;
- if pwfx^.wBitsperSample = 8 then
- begin
- if pwfx^.nChannels = 2 then
- begin
- SrcBytes := dwSrcLen and not 1;
- while (SrcBytes > 0) do
- begin
- { the left channel }
- s := (PByte(pSrc)^ - 128);
- SumL := SumL + s;
- SumL2:= SumL2 + Long(s)*s;
- { the right channel }
- s := (PByte(pSrc+1)^ - 128);
- SumR := SumR + s;
- SumR2:= SumR2 + Long(s)*s;
- inc(Samples);
- inc(pSrc, 2*sizeOf(Byte));
- dec(SrcBytes, 2*sizeOf(Byte));
- end;
- if Samples > 0 then
- begin
- AvgL := Round(SumL/Samples);
- if AvgL <> 0 then
- RmsL := Round(Sqrt(SumL2/Samples-(Long(AvgL)*AvgL)));
- AvgR := Round(SumR/Samples);
- if AvgR <> 0 then
- RmsR := Round(Sqrt(SumR2/Samples-(Long(AvgR)*AvgR)));
- end;
- end
- else
- begin
- SrcBytes := dwSrcLen;
- while (SrcBytes > 0) do
- begin
- { we have only one channel }
- s := (PByte(pSrc)^ - 128);
- SumL := SumL + s;
- SumL2:= SumL2 + Long(s)*s;
- inc(Samples);
- inc(pSrc, sizeOf(Byte));
- dec(SrcBytes, sizeOf(Byte));
- end;
- if Samples > 0 then
- begin
- AvgL := Round(SumL/Samples);
- if AvgL <> 0 then
- RmsL := Round(Sqrt(SumL2/Samples-(Long(AvgL)*AvgL)));
- end;
- AvgR := AvgL;
- RmsR := RmsL;
- end;
- end
- else
- begin
- if pwfx^.nChannels = 2 then
- begin
- SrcBytes := dwSrcLen and not 1;
- while (SrcBytes > 0) do
- begin
- { the left channel }
- s := PSmallint(pSrc)^;
- SumL := SumL + s;
- SumL2:= SumL2 + Long(s)*s;
- { the right channel }
- s := PSmallint(pSrc+2)^;
- SumR := SumR + s;
- SumR2:= SumR2 + Long(s)*s;
- inc(Samples);
- inc(pSrc, 2*sizeOf(SmallInt));
- dec(SrcBytes, 2*sizeOf(Smallint));
- end;
- if Samples > 0 then
- begin
- AvgL := Round(SumL/Samples);
- if AvgL <> 0 then
- RmsL := Round(Sqrt(SumL2/Samples-(Long(AvgL)*AvgL)));
- AvgR := Round(SumR/Samples);
- if AvgR <> 0 then
- RmsR := Round(Sqrt(SumR2/Samples-(Long(AvgR)*AvgR)));
- end;
- end
- else
- begin
- SrcBytes := dwSrcLen and not 1;
- while (SrcBytes > 0) do
- begin
- { we have only one channel }
- s := PSmallint(pSrc)^;
- SumL := SumL + s;
- SumL2:= SumL2 + Long(s)*s;
- inc(Samples);
- inc(pSrc, sizeOf(SmallInt));
- dec(SrcBytes, sizeOf(SmallInt));
- end;
- if Samples > 0 then
- begin
- AvgL := Round(SumL/Samples);
- if AvgL <> 0 then
- RmsL := Round(Sqrt(SumL2/Samples-(Long(AvgL)*AvgL)));
- end;
- AvgR := AvgL;
- RmsR := RmsL;
- end;
- end;
- end;
- {*************************************************************************}
- function pcmVolume(pwfx: PWaveFormatEx; lpData: PChar; dwSrcLen: TDataSize;
- LeftVolume, RightVolume: Longint): Boolean;
- begin
- Result := False;
- if (pwfx = nil) or (pwfx^.wFormatTag <> WAVE_FORMAT_PCM) then exit;
- if (pwfx^.wBitsPerSample = 8) then
- begin
- if (pwfx^.nChannels = 1) then
- Result := pcmVolume8M(lpData, dwSrcLen, LeftVolume)
- else
- Result := pcmVolume8S(lpData, dwSrcLen, LeftVolume, RightVolume);
- end
- else
- begin
- if (pwfx^.nChannels = 1) then
- Result := pcmVolume16M(lpData, dwSrcLen, LeftVolume)
- else
- Result := pcmVolume16S(lpData, dwSrcLen, LeftVolume, RightVolume);
- end;
- end;
- {*************************************************************************}
- procedure pcmReverse(pwfx: PWaveFormatEx; lpData: PChar; dwSrcLen: TDataSize);
- var
- Temp: Longint;
- lpSource,pTemp: PChar;
- begin
- if (pwfx = nil) or (pwfx^.wFormatTag <> WAVE_FORMAT_PCM) then exit;
- pTemp := @Temp;
- if (pwfx^.wBitsPerSample = 8) then
- begin
- if (pwfx^.nChannels = 1) then
- begin
- lpSource := (lpData+dwSrcLen-sizeOf(Byte));
- dwSrcLen := dwSrcLen div 2;
- while (dwSrcLen > 0) do
- begin
- PByte(pTemp)^ := PByte(lpData)^;
- PByte(lpData)^ := PByte(lpSource)^;
- PByte(lpSource)^:= PByte(pTemp)^;
- inc(lpData,sizeOf(Byte));
- dec(lpSource,sizeOf(Byte));
- dec(dwSrcLen,sizeOf(Byte));
- end;
- end
- else
- begin
- lpSource := (lpData+dwSrcLen-sizeOf(Word));
- dwSrcLen := dwSrcLen div 2;
- while (dwSrcLen > 0) do
- begin
- PWord(pTemp)^ := PWord(lpData)^;
- PWord(lpData)^ := PWord(lpSource)^;
- PWord(lpSource)^:= PWord(pTemp)^;
- inc(lpData,sizeOf(Word));
- dec(lpSource,sizeOf(Word));
- dec(dwSrcLen,sizeOf(Word));
- end;
- end;
- end
- else
- begin
- if (pwfx^.nChannels = 1) then
- begin
- lpSource := (lpData+dwSrcLen-sizeOf(Smallint));
- dwSrcLen := dwSrcLen div 2;
- while (dwSrcLen > 0) do
- begin
- PSmallint(pTemp)^ := PSmallint(lpData)^;
- PSmallint(lpData)^ := PSmallint(lpSource)^;
- PSmallint(lpSource)^:= PSmallint(pTemp)^;
- inc(lpData,sizeOf(Smallint));
- dec(lpSource,sizeOf(Smallint));
- dec(dwSrcLen,sizeOf(Smallint));
- end;
- end
- else
- begin
- lpSource := (lpData+dwSrcLen-sizeOf(Longint));
- dwSrcLen := dwSrcLen div 2;
- while (dwSrcLen > 0) do
- begin
- PLongint(pTemp)^ := PLongint(lpData)^;
- PLongint(lpData)^ := PLongint(lpSource)^;
- PLongint(lpSource)^:= PLongint(pTemp)^;
- inc(lpData,sizeOf(Longint));
- dec(lpSource,sizeOf(Longint));
- dec(dwSrcLen,sizeOf(Longint));
- end;
- end;
- end;
- end;
- {*************************************************************************}
- function pcmPitchChange(pwfx: PWaveFormatEx; pSrc,pDst: PChar;
- var SrcLen,DstLen,IncValue: Longint; Factor: Longint): Longint;
- begin
- Result := 0;
- if (pwfx = nil) or (pwfx^.wFormatTag <> WAVE_FORMAT_PCM) then exit;
- if (pwfx^.wBitsPerSample = 8) then
- begin
- if (pwfx^.nChannels = 1) then
- Result := pcmPitchChange8M(pSrc, pDst, SrcLen, DstLen, IncValue, Factor)
- else
- Result := pcmPitchChange8S(pSrc, pDst, SrcLen, DstLen, IncValue, Factor);
- end
- else
- begin
- if (pwfx^.nChannels = 1) then
- Result := pcmPitchChange16M(pSrc, pDst, SrcLen, DstLen, IncValue, Factor)
- else
- Result := pcmPitchChange16S(pSrc, pDst, SrcLen, DstLen, IncValue, Factor);
- end;
- end;
- {*************************************************************************}
- procedure pcmFindSilenceEnd(pwfx: PWaveFormatEx; pSrc: PChar; dwSrcLen: TDataSize;
- Threshold: Longint; var SilenceEnd: Longint);
- var
- SrcNumBytes: Longint;
- begin
- SilenceEnd := -1;
- if (Threshold < 0) then Threshold := 0;
- if pwfx^.wBitsperSample = 8 then
- begin
- if pwfx^.nChannels = 2 then
- begin
- SrcNumBytes := dwSrcLen and not 1;
- while (SrcNumBytes > 0) do
- begin
- if (abs(PByte(pSrc)^ - 128) > Threshold) or { the left channel }
- (abs(PByte(pSrc+1)^ - 128) > Threshold) then { the right channel }
- begin
- SilenceEnd := dwSrcLen-SrcNumBytes;
- exit;
- end;
- inc(pSrc, 2*sizeOf(Byte));
- dec(SrcNumBytes, 2*sizeOf(Byte));
- end;
- end
- else
- begin
- SrcNumBytes := dwSrcLen;
- while (SrcNumBytes > 0) do
- begin
- { we have only one channel }
- if (abs(PByte(pSrc)^ -128) > Threshold) then
- begin
- SilenceEnd := dwSrcLen-SrcNumBytes;
- exit;
- end;
- inc(pSrc, sizeOf(Byte));
- dec(SrcNumBytes, sizeOf(Byte));
- end;
- end;
- end
- else
- begin
- if pwfx^.nChannels = 2 then
- begin
- SrcNumBytes := dwSrcLen and not 3;
- while (SrcNumBytes > 0) do
- begin
- if (abs(PSmallint(pSrc)^) > Threshold) or { the left channel }
- (abs(PSmallint(pSrc+2)^) > Threshold) then { the right channel }
- begin
- SilenceEnd := dwSrcLen-SrcNumBytes;
- exit;
- end;
- inc(pSrc, 2*sizeOf(SmallInt));
- dec(SrcNumBytes, 2*sizeOf(SmallInt));
- end;
- end
- else
- begin
- SrcNumBytes := dwSrcLen and not 1;
- while (SrcNumBytes > 0) do
- begin
- { we have only one channel }
- if (abs(PSmallint(pSrc)^) > Threshold) then
- begin
- SilenceEnd := dwSrcLen-SrcNumBytes;
- exit;
- end;
- inc(pSrc, sizeOf(SmallInt));
- dec(SrcNumBytes, sizeOf(SmallInt));
- end;
- end;
- end;
- end;
- {*************************************************************************}
- procedure pcmFindSilenceStart(pwfx: PWaveFormatEx; pSrc: PChar; dwSrcLen: TDataSize;
- Threshold: Longint; var SilenceStart: Longint);
- var
- SrcNumBytes: Longint;
- begin
- SilenceStart := -1;
- if (Threshold < 0) then Threshold := 0;
- if pwfx^.wBitsperSample = 8 then
- begin
- if pwfx^.nChannels = 2 then
- begin
- SrcNumBytes := dwSrcLen and not 1;
- while (SrcNumBytes > 0) do
- begin
- if (abs(PByte(pSrc)^ - 128) <= Threshold) and { the left channel }
- (abs(PByte(pSrc+1)^ - 128) <= Threshold) then { the right channel }
- begin
- if (SilenceStart = -1) then
- SilenceStart := dwSrcLen-SrcNumBytes;
- end
- else
- begin
- SilenceStart := -1;
- end;
- inc(pSrc, 2*sizeOf(Byte));
- dec(SrcNumBytes, 2*sizeOf(Byte));
- end;
- end
- else
- begin
- SrcNumBytes := dwSrcLen;
- while (SrcNumBytes > 0) do
- begin
- { we have only one channel }
- if (abs(PByte(pSrc)^ -128) <= Threshold) then
- begin
- if (SilenceStart = -1) then
- SilenceStart := dwSrcLen-SrcNumBytes;
- end
- else
- begin
- SilenceStart := -1;
- end;
- inc(pSrc, sizeOf(Byte));
- dec(SrcNumBytes, sizeOf(Byte));
- end;
- end;
- end
- else
- begin
- if pwfx^.nChannels = 2 then
- begin
- SrcNumBytes := dwSrcLen and not 3;
- while (SrcNumBytes > 0) do
- begin
- if (abs(PSmallint(pSrc)^) <= Threshold) and { the left channel }
- (abs(PSmallint(pSrc+2)^) <= Threshold) then { the right channel }
- begin
- if (SilenceStart = -1) then
- SilenceStart := dwSrcLen-SrcNumBytes;
- end
- else
- begin
- SilenceStart := -1;
- end;
- inc(pSrc, 2*sizeOf(SmallInt));
- dec(SrcNumBytes, 2*sizeOf(SmallInt));
- end;
- end
- else
- begin
- SrcNumBytes := dwSrcLen and not 1;
- while (SrcNumBytes > 0) do
- begin
- { we have only one channel }
- if (abs(PSmallint(pSrc)^) <= Threshold) then
- begin
- if (SilenceStart = -1) then
- SilenceStart := dwSrcLen-SrcNumBytes;
- end
- else
- begin
- SilenceStart := -1;
- end;
- inc(pSrc, sizeOf(SmallInt));
- dec(SrcNumBytes, sizeOf(SmallInt));
- end;
- end;
- end;
- end;
- {*************************************************************************}
- {$IFDEF USEASM}
- {$IFDEF WIN32}{$L MMPCM32.OBJ}{$ELSE}{$L MMPCM16.OBJ}{$ENDIF}
- {$F+}
- function pcmSampleClip8(Sample: SmallInt): ShortInt; external;
- function pcmSampleClip16(Sample: Longint): SmallInt; external;
- function pcmSampleVolume8(Sample: Shortint; Volume: Longint): ShortInt; external;
- function pcmSampleVolume16(Sample: Smallint; Volume: Longint): SmallInt; external;
- function pcmVolume8M(lpData: PChar; dwSrcLen, Volume: Longint): Boolean; external;
- function pcmVolume8S(lpData: PChar; dwSrcLen, LeftVolume, RightVolume: Longint): Boolean; external;
- function pcmVolume16M(lpData: PChar; dwSrcLen, Volume: Longint): Boolean; external;
- function pcmVolume16S(lpData: PChar; dwSrcLen, LeftVolume, RightVolume: Longint): Boolean; external;
- procedure pcmFindPeak(pwfx: PWaveFormatEx; pSrc: PChar; dwSrcLen: TDataSize;
- var PeakL, PeakR: SmallInt); external;
- procedure pcmFindMinMax(pwfx: PWaveFormatEx; pSrc: PChar; dwSrcLen: TDataSize;
- var MinL, MaxL, MinR, MaxR: SmallInt); external;
- function pcmConvertSizeOutputData(pwfDst, pwfSrc: PPCMWaveFormat;
- NumBytesSrc: Longint): Longint; external;
- function pcmConvert(pwfDst: PPCMWaveFormat; pDst: PChar;
- pwfSrc: PPCMWaveFormat; pSrc: PChar;
- dwSrcLen: Cardinal): Cardinal; external;
- {$F-}
- {$ELSE}
- (*************************************************************************)
- function pcmSampleClip8(Sample: SmallInt): ShortInt;
- const
- ClipValue = 127;
- begin
- if (Sample < -ClipValue) then
- begin
- Result := -ClipValue;
- Overflow := True;
- end
- else if (Sample > ClipValue) then
- begin
- Result := ClipValue;
- Overflow := True;
- end
- else
- Result := Sample;
- end;
- (*************************************************************************)
- function pcmSampleClip16(Sample: Longint): SmallInt;
- const
- ClipValue = 32767;
- begin
- if (Sample < -ClipValue) then
- begin
- Result := -ClipValue;
- Overflow := True;
- end
- else if (Sample > ClipValue) then
- begin
- Result := ClipValue;
- Overflow := True;
- end
- else
- Result := Sample;
- end;
- (*************************************************************************)
- function pcmSampleVolume8(Sample: ShortInt; Volume: Longint): ShortInt;
- begin
- Result := 128 + ((Sample-128) * Volume) div VOLUMEBASE;
- end;
- (*************************************************************************)
- function pcmSampleVolume16(Sample: Smallint; Volume: Longint): Smallint;
- begin
- Result := (Sample * Volume) div VOLUMEBASE;
- end;
- (*************************************************************************)
- function pcmVolume8M(lpData: PChar; dwSrcLen: TDataSize; Volume: Longint): Boolean;
- var
- s: Smallint;
- begin
- Overflow := False;
- while (dwSrcLen > 0) do
- begin
- s := 128+((PByte(lpData)^-128) * Volume) div VOLUMEBASE;
- PByte(lpData)^ := pcmSampleClip8(s);
- inc(lpData, sizeOf(Byte));
- dec(dwSrcLen, sizeOf(Byte));
- end;
- Result := Overflow;
- end;
- (*************************************************************************)
- function pcmVolume8S(lpData: PChar; dwSrcLen: TDataSize; LeftVolume, RightVolume: Longint): Boolean;
- var
- s: Smallint;
- begin
- Overflow := False;
- dwSrcLen := dwSrcLen and not 1;
- while (dwSrcLen > 0) do
- begin
- s := 128+((PByte(lpData)^-128) * LeftVolume) div VOLUMEBASE;
- PByte(lpData)^ := pcmSampleClip8(s);
- inc(lpData, sizeOf(Byte));
- s := 128+((PByte(lpData)^-128) * RightVolume) div VOLUMEBASE;
- PByte(lpData)^ := pcmSampleClip8(s);
- inc(lpData, sizeOf(Byte));
- dec(dwSrcLen, 2*sizeOf(Byte));
- end;
- Result := Overflow;
- end;
- (*************************************************************************)
- function pcmVolume16M(lpData: PChar; dwSrcLen: TDataSize; Volume: Longint): Boolean;
- var
- s: Longint;
- begin
- Overflow := False;
- dwSrcLen := dwSrcLen and not 1;
- while (dwSrcLen > 0) do
- begin
- s := (PSmallint(lpData)^ * Volume) div VOLUMEBASE;
- PSmallint(lpData)^ := pcmSampleClip16(s);
- inc(lpData, sizeOf(Smallint));
- dec(dwSrcLen, sizeOf(Smallint));
- end;
- Result := Overflow;
- end;
- (*************************************************************************)
- function pcmVolume16S(lpData: PChar; dwSrcLen: TDataSize; LeftVolume, RightVolume: Longint): Boolean;
- var
- s: Longint;
- begin
- Overflow := False;
- dwSrcLen := dwSrcLen and not 3;
- while (dwSrcLen > 0) do
- begin
- s := (PSmallint(lpData)^ * LeftVolume) div VOLUMEBASE;
- PSmallint(lpData)^ := pcmSampleClip16(s);
- inc(lpData, sizeOf(Smallint));
- s := (PSmallint(lpData)^ * RightVolume) div VOLUMEBASE;
- PSmallint(lpData)^ := pcmSampleClip16(s);
- inc(lpData, sizeOf(Smallint));
- dec(dwSrcLen, 2*sizeOf(Smallint));
- end;
- Result := Overflow;
- end;
- {*************************************************************************}
- {* find the peak value in pSrc: 8/16 bit, mono/stereo *}
- {*************************************************************************}
- procedure pcmFindPeak(pwfx: PWaveFormatEx; pSrc: PChar; dwSrcLen: TDataSize;
- var PeakL, PeakR: SmallInt);
- var
- SrcNumBytes,sd: Longint;
- pL,pR,sw: Smallint;
- begin
- PeakL := 0;
- PeakR := 0;
- pR := 0;
- pL := 0;
- if pwfx^.wBitsperSample = 8 then
- begin
- if pwfx^.nChannels = 2 then
- begin
- SrcNumBytes := dwSrcLen and not 1;
- while (SrcNumBytes > 0) do
- begin
- { the left channel }
- sw := PByte(pSrc)^ - 128;
- if abs(sw) > pL then
- begin
- PeakL := sw;
- pL := Min(abs(sw),127);
- end;
- { the right channel }
- sw := PByte(pSrc+1)^ - 128;
- if abs(sw) > pR then
- begin
- PeakR := sw;
- pR := Min(abs(sw),127);
- end;
- inc(pSrc, 2*sizeOf(Byte));
- dec(SrcNumBytes, 2*sizeOf(Byte));
- end;
- PeakL := PeakL + 128;
- PeakR := PeakR + 128;
- end
- else
- begin
- SrcNumBytes := dwSrcLen;
- while (SrcNumBytes > 0) do
- begin
- { we have only one channel }
- sw := PByte(pSrc)^ -128;
- if abs(sw) > pL then
- begin
- PeakL := sw;
- pL := Min(abs(sw),127);
- end;
- inc(pSrc, sizeOf(Byte));
- dec(SrcNumBytes, sizeOf(Byte));
- end;
- PeakL := PeakL + 128;
- PeakR := PeakL;
- end;
- end
- else
- begin
- if pwfx^.nChannels = 2 then
- begin
- SrcNumBytes := dwSrcLen and not 3;
- while (SrcNumBytes > 0) do
- begin
- { the left channel }
- sd := PSmallint(pSrc)^;
- if abs(sd) > pL then
- begin
- PeakL := sd;
- pL := Min(abs(sd),32767);
- end;
- { the right channel }
- sd := PSmallint(pSrc+2)^;
- if abs(sd) > pR then
- begin
- PeakR := sd;
- pR := Min(abs(sd),32767);
- end;
- inc(pSrc, 2*sizeOf(SmallInt));
- dec(SrcNumBytes, 2*sizeOf(SmallInt));
- end;
- end
- else
- begin
- SrcNumBytes := dwSrcLen and not 1;
- while (SrcNumBytes > 0) do
- begin
- { we have only one channel }
- sd := PSmallint(pSrc)^;
- if abs(sd) > pL then
- begin
- PeakL := sd;
- pL := Min(abs(sd),32767);
- end;
- inc(pSrc, sizeOf(SmallInt));
- dec(SrcNumBytes, sizeOf(SmallInt));
- end;
- PeakR := PeakL;
- end;
- end;
- end;
- {*************************************************************************}
- {* find the signed Min/Max value in pSrc: 8/16 bit, mono/stereo *}
- {*************************************************************************}
- procedure pcmFindMinMax(pwfx: PWaveFormatEx; pSrc: PChar; dwSrcLen: TDataSize;
- var MinL, MaxL, MinR, MaxR: SmallInt);
- var
- SrcNumBytes: Longint;
- i, MinIdx_L, MaxIdx_L, MinIdx_R, MaxIdx_R: integer;
- begin
- MinIdx_L := 0;
- MaxIdx_L := 0;
- MinIdx_R := 0;
- MaxIdx_R := 0;
- i := 0;
- if pwfx^.wBitsperSample = 8 then
- begin
- MinL := 128;
- MaxL := 128;
- MinR := 128;
- MaxR := 128;
- if pwfx^.nChannels = 2 then
- begin
- SrcNumBytes := dwSrcLen and not 1;
- if (SrcNumBytes > 0) then
- begin
- MinL := 127;
- MaxL := -128;
- MinR := 127;
- MaxR := -128;
- while (SrcNumBytes > 0) do
- begin
- { the left channel }
- if PByte(pSrc)^ -128 < MinL then
- begin
- MinL := PByte(pSrc)^ -128;
- MinIdx_L := i;
- end;
- if PByte(pSrc)^ -128 > MaxL then
- begin
- MaxL := PByte(pSrc)^ -128;
- MaxIdx_L := i;
- end;
- { the right channel }
- if PByte(pSrc+1)^ -128 < MinR then
- begin
- MinR := PByte(pSrc+1)^ -128;
- MinIdx_R := i;
- end;
- if PByte(pSrc+1)^ -128 > MaxR then
- begin
- MaxR := PByte(pSrc+1)^ -128;
- MaxIdx_R := i;
- end;
- inc(pSrc, 2*sizeOf(Byte));
- dec(SrcNumBytes, 2*sizeOf(Byte));
- inc(i);
- end;
- if MaxIdx_L < MinIdx_L then SwapSmall(MinL, MaxL);
- if MaxIdx_R < MinIdx_R then SwapSmall(MinR, MaxR);
- MinL := MinL + 128;
- MaxL := MaxL + 128;
- MinR := MinR + 128;
- MaxR := MaxR + 128;
- end;
- end
- else
- begin
- SrcNumBytes := dwSrcLen;
- if (SrcNumBytes > 0) then
- begin
- MinL := 127;
- MaxL := -128;
- while (SrcNumBytes > 0) do
- begin
- { we have only one channel }
- if PByte(pSrc)^ -128 < MinL then
- begin
- MinL := PByte(pSrc)^ -128;
- MinIdx_L := i;
- end;
- if PByte(pSrc)^ -128 > MaxL then
- begin
- MaxL := PByte(pSrc)^ -128;
- MaxIdx_L := i;
- end;
- inc(pSrc, sizeOf(Byte));
- dec(SrcNumBytes, sizeOf(Byte));
- inc(i);
- end;
- if MaxIdx_L < MinIdx_L then SwapSmall(MinL, MaxL);
- MinL := MinL + 128;
- MaxL := MaxL + 128;
- MinR := MinL;
- MaxR := MaxL;
- end;
- end;
- end
- else
- begin
- MinL := 0;
- MaxL := 0;
- MinR := 0;
- MaxR := 0;
- if pwfx^.nChannels = 2 then
- begin
- SrcNumBytes := dwSrcLen and not 3;
- if (SrcNumBytes > 0) then
- begin
- MinL := 32767;
- MaxL := -32768;
- MinR := 32767;
- MaxR := -32768;
- while (SrcNumBytes > 0) do
- begin
- { the left channel }
- if PSmallInt(pSrc)^ < MinL then
- begin
- MinL := PSmallint(pSrc)^;
- MinIdx_L := i;
- end;
- if PSmallInt(pSrc)^ > MaxL then
- begin
- MaxL := PSmallint(pSrc)^;
- MaxIdx_L := i;
- end;
- { the right channel }
- if PSmallint(pSrc+2)^ < MinR then
- begin
- MinR := PSmallint(pSrc+2)^;
- MinIdx_R := i;
- end;
- if PSmallint(pSrc+2)^ > MaxR then
- begin
- MaxR := PSmallint(pSrc+2)^;
- MaxIdx_R := i;
- end;
- inc(pSrc, 2*sizeOf(SmallInt));
- dec(SrcNumBytes, 2*sizeOf(SmallInt));
- inc(i);
- end;
- if MaxIdx_L < MinIdx_L then SwapSmall(MinL, MaxL);
- if MaxIdx_R < MinIdx_R then SwapSmall(MinR, MaxR);
- end;
- end
- else
- begin
- { we have only one channel }
- SrcNumBytes := dwSrcLen and not 1;
- if (SrcNumBytes > 0) then
- begin
- MinL := 32767;
- MaxL := -32768;
- while (SrcNumBytes > 0) do
- begin
- { we have only one channel }
- if PSmallInt(pSrc)^ < MinL then
- begin
- MinL := PSmallint(pSrc)^;
- MinIdx_L := i;
- end;
- if PSmallInt(pSrc)^ > MaxL then
- begin
- MaxL := PSmallint(pSrc)^;
- MaxIdx_L := i;
- end;
- inc(pSrc, sizeOf(SmallInt));
- dec(SrcNumBytes, sizeOf(SmallInt));
- inc(i);
- end;
- if MaxIdx_L < MinIdx_L then SwapSmall(MinL, MaxL);
- MinR := MinL;
- MaxR := MaxL;
- end;
- end;
- end;
- end;
- {*************************************************************************}
- {* all formats: 8/16 bit, Mono/Stereo, frequency: 1..$FFFFFF *}
- {*************************************************************************}
- function pcmConvertSizeOutputData(pwfDst, pwfSrc: PPCMWaveFormat;
- NumBytesSrc: Longint): Longint;
- Var
- nSamples: Longint;
- begin
- (* OutSamples := (SrcSamples * DstSampleRate) div SrcSampleRate *)
- nSamples := wioBytesToSamples(PWaveFormatEx(pwfSrc), NumBytesSrc);
- nSamples := muldiv32(nSamples, pwfDst^.wf.nSamplesPerSec, pwfSrc^.wf.nSamplesPerSec);
- Result := wioSamplesToBytes(PWaveFormatEx(pwfDst), nSamples);
- end;
- {*************************************************************************}
- {* convert all: 8/16 bit, Mono/Stereo, frequency: 1..$FFFFFF *}
- {*************************************************************************}
- function pcmConvert(pwfDst: PPCMWaveFormat; pDst: PChar;
- pwfSrc: PPCMWaveFormat; pSrc: PChar;
- dwSrcLen: Cardinal): Cardinal;
- Var
- newSample16: array[0..1] of SmallInt;
- newSample8: array[0..1] of Byte;
- dwSrcSampleRate, dwDstSampleRate: Longint;
- wSrcChannels, wDstChannels: Word;
- wSrcBytesPS, wDstBytesPS: Word; { Bytes per Sample }
- dwNumSamples, dwSum: Longint;
- dwTotalDst: integer;
- fBPSUp: Boolean; { convert BPS up }
- fBPSDown: Boolean; { convert BPS down }
- i: integer;
- {-------------------}
- Procedure ReadSample;
- Var
- ch: integer;
- begin
- { get the source sample(s) }
- for ch := 0 to wSrcChannels-1 do
- begin
- if fBPSUp then
- begin
- newSample16[ch] := (PByte(pSrc)^ shl 8) xor $8000;
- inc(pSrc);
- end
- else if fBPSDown then
- begin
- newSample8[ch] := ((PSmallInt(pSrc)^ xor $8000) + $0080) shr 8;
- inc(pSrc,2);
- end
- else if (wSrcBytesPS <= 1) then
- begin
- newSample8[ch] := PByte(pSrc)^;
- inc(pSrc);
- end
- else
- begin
- newSample16[ch] := PSmallint(pSrc)^;
- inc(pSrc,2);
- end;
- end;
- end;
- {--------------------}
- procedure WriteSample;
- Var
- ch: integer;
- begin
- for ch := 0 to wDstChannels-1 do
- begin
- if fBPSDown or (wDstBytesPS <= 1) then
- begin
- if (wSrcChannels = wDstChannels) then
- PByte(pDst)^ := newSample8[ch]
- else if (wSrcChannels < wDstChannels) then
- PByte(pDst)^ := newSample8[0]
- else { mix the two channels }
- PByte(pDst)^ := MinMax(Word(newSample8[0]) + newSample8[1],0,255);
- inc(pDst);
- inc(dwTotalDst);
- end
- else
- begin
- if (wSrcChannels = wDstChannels) then
- PSmallInt(pDst)^ := newSample16[ch]
- else if (wSrcChannels < wDstChannels) then
- PSmallInt(pDst)^ := newSample16[0]
- else { mix the two channels }
- PSmallInt(pDst)^ := MinMax(Longint(newSample16[0]) + newSample16[1],-32768,32765);
- inc(pDst,2);
- inc(dwTotalDst, 2);
- end;
- end;
- end;
- {-- MAIN --}
- begin
- fBPSup := False;
- fBPSDown := False;
- wSrcBytesPS := pwfSrc^.wBitsPerSample shr 3;
- wDstBytesPS := pwfDst^.wBitsPerSample shr 3;
- wSrcChannels := pwfSrc^.wf.nChannels;
- wDstChannels := pwfDst^.wf.nChannels;
- dwSrcSampleRate := pwfSrc^.wf.nSamplesPerSec;
- dwDstSampleRate := pwfDst^.wf.nSamplesPerSec;
- { if wave formats are the same just return the input buffer }
- if ((wSrcChannels = wDstChannels) and
- (dwSrcSampleRate = dwDstSampleRate) and
- (wSrcBytesPS = wDstBytesPS)) then
- begin
- move(pSrc^, pDst^, dwSrcLen);
- Result := dwSrcLen;
- exit;
- end;
- dwNumSamples := dwSrcLen div wSrcBytesPS div wSrcChannels;
- if (wSrcBytesPS <= 1) and (wDstBytesPS > 1) then fBPSUp := True;
- if (wSrcBytesPS > 1) and (wDstBytesPS <= 1) then fBPSDown := True;
- dwTotalDst := 0;
- { PCM format (8 or 16 bit, mono/stereo, and sample rate). }
- if (dwSrcSampleRate > dwDstSampleRate) then
- begin
- { down sampling, skip samples }
- dwSum := dwSrcSampleRate div 2;
- for i := 0 to dwNumSamples-1 do
- begin
- ReadSample;
- dwSum := dwSum - dwDstSampleRate;
- if dwSum < 0 then
- begin
- WriteSample;
- dwSum := dwSum + dwSrcSampleRate;
- end;
- end;
- end
- else
- begin
- { up sampling, repeat samples }
- dwSum := dwDstSampleRate div 2;
- for i := 0 to dwNumSamples-1 do
- begin
- ReadSample;
- while dwSum >= 0 do
- begin
- WriteSample;
- dwSum := dwSum - dwSrcSampleRate;
- end;
- dwSum := dwSum + dwDstSampleRate;
- end;
- end;
- Result := dwTotalDst;
- end;
- {$ENDIF}
- {*************************************************************************}
- {* only standard: 8/16 bit PCM *}
- {*************************************************************************}
- function pcmBitsPerSampleAlign(nDstBitsPS: Word; pDst: PChar;
- nSrcBitsPS: Word; pSrc: PChar;
- dwSrcLen: Cardinal): Cardinal;
- Var
- i: integer;
- dwNumSamples: Longint;
- dwTotalDst: Longint;
- begin
- if (nSrcBitsPS = nDstBitsPS) then
- begin
- move(pSrc^, pDst^, dwSrcLen);
- Result := dwSrcLen;
- exit;
- end;
- dwNumSamples := dwSrcLen div (nSrcBitsPS shr 3);
- dwTotalDst := 0;
- if (nSrcBitsPS > nDstBitsPS) then
- begin { convert from 16 bit to 8 bit }
- for i := 0 to dwNumSamples-1 do
- begin
- PByte(pDst)^ := (PSmallInt(pSrc)^ div 256) + 128;
- inc(pSrc, 2);
- inc(pDst);
- inc(dwTotalDst);
- end;
- end
- else
- begin { convert from 8 bit to 16 bit }
- for i := 0 to dwNumSamples-1 do
- begin
- PSmallInt(pDst)^ := Smallint(PByte(pSrc)^-128) * 256;
- inc(pSrc);
- inc(pDst, 2);
- inc(dwTotalDst, 2);
- end;
- end;
- Result := dwTotalDst;
- end;
- {*************************************************************************}
- {* only standard: Mono/Stereo PCM *}
- {*************************************************************************}
- function pcmChannelAlign(nDstChannels: Word; pDst: PChar;
- nSrcChannels: Word; pSrc: PChar;
- nBitsPS: Word; dwSrcLen: Cardinal): Cardinal;
- Var
- i: integer;
- dwNumSamples: Longint;
- dwTotalDst: Longint;
- begin
- if (nSrcChannels = nDstChannels) then
- begin
- move(pSrc^, pDst^, dwSrcLen);
- Result := dwSrcLen;
- exit;
- end;
- dwNumSamples := dwSrcLen div (nBitsPS shr 3) div nSrcChannels;
- dwTotalDst := 0;
- if (nSrcChannels < nDstChannels) then { convert from mono to stereo }
- begin
- if (nBitsPS = 8) then { 8 bit }
- begin
- for i := 0 to dwNumSamples-1 do
- begin
- PByte(pDst)^ := PByte(pSrc)^;
- PByte(pDst+1)^ := PByte(pSrc)^;
- inc(pSrc);
- inc(pDst, 2);
- inc(dwTotalDst, 2);
- end;
- end
- else { 16 bit }
- begin
- for i := 0 to dwNumSamples-1 do
- begin
- PSmallInt(pDst)^ := PSmallInt(pSrc)^;
- PSmallInt(pDst+2)^ := PSmallInt(pSrc)^;
- inc(pSrc, 2);
- inc(pDst, 4);
- inc(dwTotalDst, 4);
- end;
- end;
- end
- else { convert from stereo to mono }
- begin
- if (nBitsPS = 8) then { 8 bit }
- begin
- for i := 0 to dwNumSamples-1 do
- begin
- { mix the two channels }
- PByte(pDst)^ := MinMax(Word(PByte(pSrc)^)+Word(PByte(pSrc+1)^),0, 255);
- inc(pSrc, 2);
- inc(pDst);
- inc(dwTotalDst);
- end;
- end
- else { 16 bit }
- begin
- for i := 0 to dwNumSamples-1 do
- begin
- PSmallInt(pDst)^ := MinMax(Longint(PSmallInt(pSrc)^) + Longint(PSmallInt(pSrc+2)^),-32765, 32765);
- inc(pSrc, 4);
- inc(pDst, 2);
- inc(dwTotalDst, 2);
- end;
- end;
- end;
- Result := dwTotalDst;
- end;
- (*************************************************************************)
- (* this routine averages the 8 bit samples along the different channels *)
- (*************************************************************************)
- procedure pcmAvgSample8(pDst, pSrc: PChar; nSkip, nChannels: Word);
- Var
- lpB: PByte;
- sum, i,j: integer;
- begin
- for i := 0 to nChannels-1 do
- begin
- lpB := PByte(pSrc);
- inc(pSrc);
- sum := 0;
- for j := 0 to nSkip-1 do
- begin
- sum := sum + (lpB^ - 128);
- inc(lpB, nChannels);
- end;
- PByte(pDst)^ := (sum div nSkip) + 128;
- inc(pDst);
- end;
- end;
- (*************************************************************************)
- (* this routine averages the 16 bit samples along the different channels *)
- (*************************************************************************)
- procedure pcmAvgSample16(pDst, pSrc: PChar; nSkip, nChannels: Word);
- Var
- lpW: PSmallInt;
- sum: Longint;
- i,j: integer;
- begin
- for i := 0 to nChannels-1 do
- begin
- lpW := PSmallInt(pSrc);
- inc(PSmallInt(pSrc));
- sum := 0;
- for j := 0 to nSkip-1 do
- begin
- sum := sum + lpW^;
- inc(lpW, nChannels);
- end;
- PSmallInt(pDst)^ := sum div nSkip;
- inc(PSmallInt(pDst));
- end;
- end;
- (*************************************************************************)
- (* this routine interpolates the 8 Bit samples along the diff. channels *)
- (*************************************************************************)
- procedure pcmRepSample8(pDst, pSrc: PChar; nRep, nChannels: Word);
- Var
- lpB: PByte;
- diff, val: integer;
- i, j: integer;
- begin
- if (nRep > 1) then
- begin
- lpB := PByte(pDst);
- for i := 0 to nChannels-1 do
- begin
- PByte(pDst) := lpB;
- inc(lpB);
- diff := (PByte(pSrc+nChannels)^ - PByte(pSrc)^) div nRep;
- PByte(pDst)^ := pByte(pSrc)^;
- val := PByte(pSrc)^;
- inc(pDst, nChannels);
- {diff := 0; remove interpolation }
- for j := 1 to nRep-1 do
- begin
- inc(val, diff);
- PByte(pDst)^ := val;
- inc(pDst, nChannels);
- end;
- inc(pSrc);
- end;
- end;
- end;
- (*************************************************************************)
- (* this routine interpolates the 8 Bit samples along the diff. channels *)
- (*************************************************************************)
- procedure pcmRepSample16(pDst, pSrc: PChar; nRep, nChannels: Word);
- Var
- lpW: PSmallInt;
- diff, val: integer;
- i, j: integer;
- begin
- if (nRep > 1) then
- begin
- lpW := PSmallInt(pDst);
- for i := 0 to nChannels-1 do
- begin
- PSmallInt(pDst) := lpW;
- inc(lpW);
- diff := (PSmallInt(pSrc+2*nChannels)^ - PSmallInt(pSrc)^) div nRep;
- PSmallInt(pDst)^ := PSmallInt(pSrc)^;
- val := PSmallInt(pSrc)^;
- inc(PSmallInt(pDst), nChannels);
- { diff := 0; remove interpolation }
- for j := 1 to nRep-1 do
- begin
- inc(val,diff);
- PSmallInt(pDst)^ := val;
- inc(PSmallInt(pDst), nChannels);
- end;
- inc(PSmallInt(pSrc));
- end;
- end;
- end;
- {*************************************************************************}
- {* only standard: 11025Khz, 22050Khz, 44100Khz PCM !!! *}
- {*************************************************************************}
- function pcmSamplesPerSecAlign(nDstSPS: Longint; pDst: PChar;
- nSrcSPS: Longint; pSrc: PChar;
- nBitsPS, nChannels: Word;
- dwSrcLen: Cardinal): Cardinal;
- Var
- i,j: integer;
- SampleSize: DWORD;
- nRep,nSkip: DWORD;
- dwNumSamples,dwNewNumSamples: DWORD;
- dwTotalDst: Longint;
- pTmp: PChar;
- begin
- if (nSrcSPS = nDstSPS) then
- begin
- move(pSrc^, pDst^, dwSrcLen);
- Result := dwSrcLen;
- exit;
- end;
- SampleSize := (nBitsPS shr 3) * nChannels;
- dwNumSamples := dwSrcLen div SampleSize;
- nSkip := 0;
- nRep := 0;
- dwTotalDst := 0;
- if (nDstSPS > nSrcSPS) then
- begin
- { then need to add in extra samples }
- nRep := nDstSPS div nSrcSPS;
- dwNewNumSamples := dwNumSamples * nRep;
- end
- else
- begin
- { replace the sample with the average of nSkip samples }
- nSkip := nSrcSPS div nDstSPS;
- dwNewNumSamples := dwNumSamples div DWORD(Max(nSkip,1));
- end;
- if (nRep > 0) then
- begin
- if nBitsPS = 8 then
- begin
- for i := 1 to dwNumSamples-1 do
- begin
- { this routine should interpolate the 8 Bit samples }
- pcmRepSample8(pDst, pSrc, nRep, nChannels);
- inc(pSrc, SampleSize);
- inc(pDst, nRep * SampleSize);
- inc(dwTotalDst, nRep * SampleSize);
- end;
- end
- else
- begin
- for i := 1 to dwNumSamples-1 do
- begin
- { this routine should interpolate the 16 Bit samples }
- pcmRepSample16(pDst, pSrc, nRep, nChannels);
- inc(pSrc, SampleSize);
- inc(pDst, nRep * SampleSize);
- inc(dwTotalDst, nRep * SampleSize);
- end;
- end;
- { up sample last sample without filtering }
- for i := 0 to nRep-1 do
- begin
- pTmp := pSrc;
- for j := 0 to SampleSize-1 do
- begin
- pDst^ := pTmp^;
- inc(pTmp);
- inc(pDst);
- inc(dwTotalDst);
- end;
- end;
- end
- else
- begin
- if nBitsPS = 8 then
- begin
- for i := 1 to dwNewNumSamples-1 do
- begin
- { this routine should average the 8 Bit samples }
- pcmAvgSample8(pDst, pSrc, nSkip, nChannels);
- inc(pSrc, nSkip * SampleSize);
- inc(pDst, SampleSize);
- inc(dwTotalDst, SampleSize);
- end;
- end
- else
- begin
- for i := 1 to dwNewNumSamples-1 do
- begin
- { this routine should average the 16 Bit samples }
- pcmAvgSample16(pDst, pSrc, nSkip, nChannels);
- inc(pSrc, nSkip * SampleSize);
- inc(pDst, SampleSize);
- inc(dwTotalDst, SampleSize);
- end;
- end;
- { just copy the last sample }
- for i := 0 to SampleSize-1 do
- begin
- pDst^:= pSrc^;
- inc(pSrc);
- inc(pDst);
- inc(dwTotalDst);
- end;
- end;
- Result := dwTotalDst;
- end;
- (*************************************************************************)
- function pcmAllocMixPool(NumTracks: integer): PMMMixPool;
- begin
- Result := GlobalAllocMem(sizeOf(TMMMixPool)+NumTracks*sizeOf(PChar));
- if Result = nil then OutOfMemoryError;
- end;
- {*************************************************************************}
- function pcmMixIt(pwfx: PWaveFormatEx;
- pDst: PChar; pTemp: PChar;
- const pSrc: PMMMixPool; NumWaves: integer;
- dwSrcLen: Longint): Boolean;
- begin
- Result := False;
- if (pwfx = nil) or (pwfx^.wFormatTag <> WAVE_FORMAT_PCM) then exit;
- if (pwfx^.wBitsPerSample = 8) then
- begin
- Result := pcmMixIt8(pDst,Pointer(pTemp),pSrc,NumWaves,dwSrcLen);
- end
- else
- begin
- Result := pcmMixIt16(pDst,Pointer(pTemp),pSrc,NumWaves,dwSrcLen);
- end;
- end;
- {*************************************************************************}
- {$IFDEF WIN32}{$L MMMIX32.OBJ}{$ELSE}{$L MMMIX16.OBJ}{$ENDIF}
- {$F+}
- function pcmMixIt8(pDst: PChar; pTemp: PSmallint;
- const pSrc: PMMMixPool; NumWaves: integer;
- dwSrcLen: Longint): Boolean; external;
- function pcmMixIt16(pDst: PChar; pTemp: PLongint;
- const pSrc: PMMMixPool; NumWaves: integer;
- dwSrcLen: Longint): Boolean; external;
- {$F-}
- {*************************************************************************}
- {$IFDEF WIN32}{$L MMPITC32.OBJ}{$ELSE}{$L MMPITC16.OBJ}{$ENDIF}
- {$F+}
- function pcmPitchChange8M(pSrc,pDst: PChar; var SrcLen,DstLen,IncValue: Longint;
- Factor: Longint): Longint; external;
- function pcmPitchChange8S(pSrc,pDst: PChar; var SrcLen,DstLen,IncValue: Longint;
- Factor: Longint): Longint; external;
- function pcmPitchChange16M(pSrc,pDst: PChar; var SrcLen,DstLen,IncValue: Longint;
- Factor: Longint): Longint; external;
- function pcmPitchChange16S(pSrc,pDst: PChar; var SrcLen,DstLen,IncValue: Longint;
- Factor: Longint): Longint; external;
- {$F-}
- end.