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

📄 mmwmixer.pas

📁 一套及时通讯的原码
💻 PAS
📖 第 1 页 / 共 3 页
字号:
         finally
            LeaveCritical;
         end;
      end;
   end;
end;

{-- TMMWaveMixer --------------------------------------------------------------}
function TMMWaveMixer.GetInputDone(index: integer): Boolean;
begin
   Result := True;
   if (index >= 0) and (index < MAXTRACKS) then
   begin
      Result := (FTracks[Index].InPort <> nil) and IsInputDone(index);
   end;
end;

{-- TMMWaveMixer --------------------------------------------------------------}
function TMMWaveMixer.GetInputLoading(index: integer): Boolean;
begin
   Result := False;
   if (index >= 0) and (index < MAXTRACKS) then
   begin
      Result := (FTracks[Index].InPort <> nil) and FTracks[index].Loading;
   end;
end;

{-- TMMWaveMixer --------------------------------------------------------------}
function TMMWaveMixer.GetInputPosition(index: integer): int64;
begin
   Result := 0;
   if (index >= 0) and (index < MAXTRACKS) then
   begin
      if (FTracks[Index].InPort <> nil) then
          Result := SamplesToTimeFormat(FTracks[index].CurPosition);
   end;
end;

{-- TMMWaveMixer --------------------------------------------------------------}
procedure TMMWaveMixer.BufferReady(lpwh: PWaveHdr);
begin
end;

{-- TMMWaveMixer --------------------------------------------------------------}
procedure TMMWaveMixer.BufferLoad(lpwh: PWaveHdr; var MoreBuffers: Boolean);
var
   nBytes,nSamples: Longint;
begin
   nSamples := lpwh^.dwBufferLength div FBPS;
   if (nSamples > (FMaxPlayTime-FLocator)) then
      nSamples := {$IFNDEF DELPHI4}Trunc{$ENDIF}(FMaxPlaytime-FLocator);
   if (nSamples < 0) then
       nSamples := 1;

   nBytes := nSamples * FBPS;

   { neue Daten laden und mischen }
   FillBuffers(nSamples);
   MixBuffers(lpwh^.lpData,nBytes);
   lpwh^.dwBytesRecorded := nBytes;

   FLocator := FLocator + nSamples;

   if (Flocator >= FMaxPlayTime) and FStarted then
   with PMMWaveHdr(lpwh)^ do
   begin
      if LoopRec.dwLoop then
      with LoopRec do
      begin
         if (dwLoopCnt > 0) then dec(dwLoopTmpCnt);
         if (dwLoopCnt = 0) or (dwLoopTmpCnt >= 0) then
         begin
            { restart the playing }
            CloseAllTracks;
            FLocator := 0;

            MoreBuffers := True;
            dwLooping := True;
         end;
      end;
   end
   else MoreBuffers := True;
end;

{-- TMMWaveMixer --------------------------------------------------------------}
procedure TMMWaveMixer.OpenPort(aPort: TMMDSPComponent);
var
   Current: TMMDSPComponent;
begin
   if (aPort = nil) then exit;

   { search the first component }
   Current := aPort;
   while (Current.Input <> nil) do
   begin
      Current := Current.Input;

      { if we have a preloader it is the first component for us }
      if Current.FPreloaded then break;
   end;

   { no go trough all components and notify }
   repeat
      if not (Current is TMMCustomSoundComponent) then
      begin
         Current.BufferSize := BufferSize;
         Current.Opened;
         Current.Started;
      end;
      Current := Current.Output;
   until (Current = nil) or (Current = Self);
end;

{-- TMMWaveMixer --------------------------------------------------------------}
procedure TMMWaveMixer.ClosePort(aPort: TMMDSPComponent);
var
   Current: TMMDSPComponent;
begin
   if (aPort = nil) then exit;

   { search the first component }
   Current := aPort;
   while (Current.Input <> nil) do Current := Current.Input;

   { no go trough all components and notify }
   repeat
      if not (Current is TMMCustomSoundComponent) then
      begin
         Current.Stopped;
         Current.Closed;
      end;
      Current := Current.Output;
   until (Current = nil) or (Current = Self);
end;

{-- TMMWaveMixer --------------------------------------------------------------}
procedure TMMWaveMixer.OpenInput(idx: integer);
var
   cvtSize: Longint;

begin
   if (FTracks[idx].Inport <> nil) then
   with FTracks[idx] do
   begin
      CurPosition   := 0;
      Done          := False;
      bMustConvert  := False;
      bCanConvert   := False;
      lpACMConvert  := nil;

      if acmMustConvert(InPort.PWaveFormat,Self.PWaveFormat) then
      begin
         bMustConvert := True;
         if acmQueryConvert(InPort.PWaveFormat,Self.PWaveFormat,True) then
         begin
            CvtSize := Min(ACM_CONVERT_SIZE,FRealBufSize);
            lpACMConvert  := acmBeginConvert(InPort.PWaveFormat,Self.PWaveFormat,
                                             PChar(FTempBuffer),CvtSize,True);
             bCanConvert := (lpACMConvert <> nil);
         end;

         if not bCanConvert then
         begin
            CloseInput(idx);
            exit;
         end;
      end;

      { open the port }
      OpenPort(InPort);
   end;
end;

{-- TMMWaveMixer --------------------------------------------------------------}
procedure TMMWaveMixer.CloseInput(idx: integer);
begin
   with FTracks[idx] do
   begin
      if (InPort <> nil) then
      begin
         Done := True;
         ClosePort(InPort);
         acmDoneConvert(lpACMConvert);

         if Loading then
         begin
            Loading := False;
            if assigned(FOnClosePort) then FOnClosePort(Self,idx);
         end;
      end;
   end;
end;

{-- TMMWaveMixer --------------------------------------------------------------}
function TMMWaveMixer.ReadFromInput(idx: integer; Buffer: PChar; nBytes: Longint): Longint;
Label CopyData;
var
   nRead: Longint;
   MoreBuffers: Boolean;
begin
   { read Data }
   Result := 0;
   if (FTracks[idx].InPort <> nil) then
   with FTracks[idx] do
   begin
      if bMustConvert then
      begin
         if bCanConvert and (lpACMConvert <> nil) then
         begin
            with lpACMConvert^ do
            begin
CopyData:
               { get some data from the conversion buffer }
               if (dwBytesConverted-dwBytesRead > 0) then
               begin
                  nRead := Min(dwBytesConverted-dwBytesRead,nBytes);
                  GlobalMoveMem((lpDstBuffer+dwBytesRead)^,(Buffer+Result)^,nRead);
                  dec(nBytes,nRead);
                  inc(dwBytesRead,nRead);
                  inc(Result,nRead);
               end;

               { do we need more data ? }
               if (nBytes > 0) and not Done then
               begin
                  FillChar(Ftwh,sizeOf(Ftwh),0);

                  Ftwh.wh.lpData := lpSrcBuffer;
                  Ftwh.wh.dwBufferLength := dwSrcBufferSize;
                  Ftwh.LoopRec.dwLoop := Loop;
                  if Loop then
                  begin
                     Ftwh.LoopRec.dwLoopCnt    := LoopCount;
                     Ftwh.LoopRec.dwLoopTmpCnt := LoopTempCount;
                     Ftwh.LoopRec.dwLooping    := False;
                  end;

                  MoreBuffers := False;
                  InPort.BufferLoad(@Ftwh,MoreBuffers);

                  if Loop then LoopTempCount := Ftwh.LoopRec.dwLoopTmpCnt;

                  nRead := Ftwh.wh.dwBytesRecorded;

                  if not MoreBuffers or (nRead <= 0) then Done := True;

                  if (nRead > 0) then
                  begin
                     if acmDoConvert(lpACMConvert,nRead) <= 0 then
                     begin
                        bCanConvert := False;
                        Done        := True;
                        exit;
                     end;

                     if not Loading then
                     begin
                        Loading := True;
                        if assigned(FOnOpenPort) then FOnOpenPort(Self,idx);
                     end;

                     goto CopyData;
                  end;
               end;
            end;
         end
         else
         begin
            Done   := True;
            Result := 0;
         end;
      end
      else if not Done then
      begin
         FillChar(Ftwh.wh,sizeOf(Ftwh),0);
         MoreBuffers := False;

         Ftwh.wh.lpData := Buffer;
         Ftwh.wh.dwBufferLength := nBytes;
         Ftwh.LoopRec.dwLoop := Loop;
         if Loop then
         begin
            Ftwh.LoopRec.dwLoopCnt    := LoopCount;
            Ftwh.LoopRec.dwLoopTmpCnt := LoopTempCount;
            Ftwh.LoopRec.dwLooping    := False;
         end;

         InPort.BufferLoad(@Ftwh,MoreBuffers);

         if Loop then LoopTempCount := Ftwh.LoopRec.dwLoopTmpCnt;

         nRead := Ftwh.wh.dwBytesRecorded;

         if not MoreBuffers or (nRead <= 0) then Done := True
         else if not Loading then
         begin
            Loading := True;
            if assigned(FOnOpenPort) then FOnOpenPort(Self,idx);
         end;

         inc(Result,nRead);
      end;
   end;
end;

{-- TMMWaveMixer --------------------------------------------------------------}
function TMMWaveMixer.IsInputDone(idx: integer): Boolean;
begin
   with FTracks[idx] do
   begin
      Result := Done and
                ((lpACMConvert = nil) or
                (lpACMConvert^.dwBytesConverted-lpACMConvert^.dwBytesRead = 0));
   end;
end;

{-- TMMWaveMixer --------------------------------------------------------------}
procedure TMMWaveMixer.FillBuffers(dwSamples: Longint);
var
   i: integer;
   BufferPos: Longint;
   nRead,nFill: Longint;
   Buffer: PChar;
   n: int64;
begin
   i := 0;
   while FStarted and FOpen and (i < MAXTRACKS) do
   begin
      EnterCritical;
      try
         Buffer := FBufferPool^[i]^.lpData;
         BufferPos := 0;
         with FTracks[i] do
         begin
            if (InPort <> nil) then
            with InPort do
            begin
               if not IsOpen then
               begin
                  { must the sample now opened ? }
                  if (FLocator+dwSamples >= StartSamplePos) and not Done then
                  begin
                     { ev.Anfang des Buffers mit 0 f黮len }
                     n := (StartSamplePos-FLocator)*FBPS - BufferPos;
                     if (n > 0) then
                     begin
                        nFill := {$IFNDEF DELPHI4}Trunc{$ENDIF}(n);
                        GlobalFillMem(Buffer^, nFill,0);
                        inc(Buffer, nFill);
                        inc(BufferPos, nFill);
                     end;
                     OpenInput(i);
                  end;
               end;

               if isOpen then
               begin
                  { Daten lesen }
                  nRead := ReadFromInput(i, Buffer, Max(dwSamples*FBPS-BufferPos,0));
                  { wurden Daten gelesen ? }
                  if (nRead > 0) then
                  begin
                     inc(Buffer, nRead);
                     inc(BufferPos, nRead);
                     CurPosition := CurPosition + (nRead div FBPS);
                  end;

                  { wenn File am Ende, dann File schlie遝n }
                  if IsInputDone(i) then
                  begin
                     CloseInput(i);
                  end;
               end;

               if (BufferPos > 0) then
               begin
                  { ev. restlichen Puffer mit 0 f黮len }
                  nFill := dwSamples*FBPS - BufferPos;
                  if (nFill > 0) then
                  begin
                     GlobalFillMem(Buffer^, nFill, 0);
                     inc(BufferPos, nFill);
                  end;
               end;
            end;
         end;

         { gelesene Bytes merken }
         FBufferPool^[i]^.dwBytesLoaded := BufferPos;
         inc(i);

      finally
         LeaveCritical;
      end;

      { let other threads have some time }
      Sleep(1);
   end;
end;

{-- TMMWaveMixer --------------------------------------------------------------}
procedure TMMWaveMixer.MixBuffers(lpBuffer: PChar; dwLength: Longint);
var
   i,nMixChannels: integer;

begin
   if not FOpen or not FStarted then exit;

   { sort out the buffers which contain realy data }
   nMixChannels := 0;
   for i := 0 to MAXTRACKS-1 do
   begin
      if (FBufferPool^[i]^.dwBytesLoaded > 0) then
      begin
         { point to this buffer }
         FMixPool^.lpBuffers[nMixChannels] := FBufferPool^[i]^.lpData;
         inc(nMixChannels);
      end;
   end;

   FMixPool^.dwLeftVolume := FLeftVolume;
   FMixPool^.dwRightVolume:= FRightVolume;

   { mix the buffers or fill with zero if no data }
   if pcmMixIt16(lpBuffer,FTempBuffer,FMixPool,nMixChannels,dwLength) then
      FOverflow := True;
end;

end.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -