📄 mmpcmsup.pas
字号:
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.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -