📄 mmwmixer.pas
字号:
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 + -