⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mmpcmsup.pas

📁 一套及时通讯的原码
💻 PAS
📖 第 1 页 / 共 5 页
字号:
   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 + -