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