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

📄 unampglibapi.pas

📁 Voice Commnucation Components for Delphi
💻 PAS
📖 第 1 页 / 共 2 页
字号:
	result := mpglib_error_noProc;
      end
      else
	result := 0;
    end
    else begin
      //
      result := mpglib_error_noLib;
      dec(proto.r_refCount);
    end;
  end
  else begin
    //
    inc(proto.r_refCount);
    result := 0;
  end;
end;

// --  --
function unloadLib(var proto: mpglib_proto): int;
begin
  if (1 = proto.r_refCount) then begin
    //
    proto.r_module := 0;
    proto.r_initMP3 := nil;
    proto.r_decodeMP3 := nil;
    proto.r_exitMP3 := nil;
    //
    dec(proto.r_refCount);
  end
  else
    if (0 < proto.r_refCount) then
      dec(proto.r_refCount);
  //
  result := 0;
end;


var
  globalLock: unaInProcessGate;

{ unaMpgLibDecoder }

// --  --
procedure unaMpgLibDecoder.afterConstruction();
begin
  inherited;
  //
  f_inStream := unaMemoryStream.create();
  f_inStream.maxCacheSize := 128;
  //
  f_MPSTR := malloc(32*1024);	// 32 K
  loadLibrary(f_proto.r_libName);
end;

// --  --
procedure unaMpgLibDecoder.beforeDestruction();
begin
  inherited;
  //
  unloadLibrary();
  mrealloc(f_MPSTR);
  freeAndNil(f_inStream);
end;

// --  --
procedure unaMpgLibDecoder.close();
begin
  stop();
end;

// --  --
constructor unaMpgLibDecoder.create(const libName: string);
begin
  inherited create();
  //
  f_proto.r_libName := libName;
end;

// --  --
procedure unaMpgLibDecoder.doWrite(data: pointer; len: unsigned);
begin
  f_inStream.write(data, len);
  //
  wakeUp();
end;

// --  --
function unaMpgLibDecoder.execute(threadIndex: unsigned): int;
var
  size: unsigned;
  chunk: pArray;
  chunkSize: unsigned;
  outChunk: array[word] of byte;
  res: int;
  done: int;
  i: unsigned;
  entered: bool;
  nothing: bool;
  giveUp: unsigned;
  offset: unsigned;
  mpegVer: int;
  layer: int;
  notUsed: bool;
begin
  chunkSize := MAXFRAMESIZE;
  chunk := malloc(chunkSize);
  res := 0;
  mpegVer := -1;
  layer := -1;
  //
  try
    while (not shouldStop) do begin
      //
      f_inStream.waitForData(100);
      //
      if (0 = f_errorCode) then begin
	//
	while (not shouldStop and (0 < f_inStream.getFirstChunkSize())) do begin
	  //
	  size := f_inStream.read(chunk, chunkSize);
	  offset := 0;
	  //
	  while (0 < size) do begin
	    //
	    if (0 = res) then begin
	      // try to locate FF
	      i := offset;
	      repeat
		//
		while (not shouldStop and
			  (i < size - 2) and
			     (
			       ($FF <> chunk[i]) or
			       ($F0 <> (chunk[i + 1] and $F0)) or
			       ($00  = (chunk[i + 1] and $06)) or
			       ($F0  = (chunk[i + 2] and $F0)) or
			       ($0C  = (chunk[i + 2] and $0C)) or
			       ((0 <= mpegVer) and (mpegVer <> ((chunk[i + 1] and $08) shr 3))) or
			       ((0 <  layer)   and (layer   <> ((chunk[i + 1] and $06) shr 1)))
			     )
		      ) do
		  inc(i);
		//
		if (i < size - 2) then begin
		  //
		  dec(size, i);
		  move(chunk[i], chunk[0], size);
		  i := 1;
		  //
		  if (0 > mpegVer) then
		    mpegVer := (chunk[1] and $08) shr 3;
		  //
		  if (1 > layer) then
		    layer := (chunk[1] and $06) shr 1;
		  //
		  if (0 < f_ensureLayer) then begin
		    //
		    case (f_ensureLayer) of

		       1: if (3 <> layer) then begin
			 mpegVer := -1;
			 layer := -1;
		       end;

		       2: if (2 <> layer) then begin
			 mpegVer := -1;
			 layer := -1;
		       end;

		       3: if (1 <> layer) then begin
			 mpegVer := -1;
			 layer := -1;
		       end;

		    end;
		    //
		  end;
		end
		else
		  size := 0;	// skip over to next block of data
		//
	      until (shouldStop or (1 > size) or ((0 < layer) and (0 <= mpegVer)));
	    end;
	    //
	    giveUp := 100;
	    entered := false;
	    repeat
	      //
	      if (globalLock.enter(100)) then begin
		//
		try
		  if (0 < size) then begin
		    //
		    try
		      res := f_proto.r_decodeMP3(f_MPSTR, chunk, size, @outChunk, sizeOf(outChunk), done)
		    except
		      // ignore all soft errors
		      res := MP3_ERR;
		      done := 0;
		      layer := -1;
		      mpegVer := -1;
		    end;
		    //
		  end
		  else
		    done := 0;
		  //
		finally
		  globalLock.leave();
		end;
		//
		entered := true;
	      end
	      else
		dec(giveUp);
	      //
	    until (entered or shouldStop or (1 > giveUp));
	    //
	    if (1 > giveUp) then
	      inc(f_enterFails);
	    //
	    nothing := (1 > done) and (0 = res);
	    //
	    while (not shouldStop and entered and (0 = res) and (0 < done)) do begin
	      //
	      notUsed := true;	// compatibility with older code
	      notifyData(@outChunk, done, notUsed);
	      //
	      //
	      giveUp := 100;
	      entered := false;
	      repeat
		//
		if (globalLock.enter(100)) then begin
		  //
		  try
		    //
		    try
		      res := f_proto.r_decodeMP3(f_MPSTR, nil, 0, @outChunk, sizeOf(outChunk), done);
		    except
		      // ignore all soft errors
		      res := MP3_ERR;
		      done := 0;
		      layer := -1;
		      mpegVer := -1;
		    end;
		    //
		  finally
		    globalLock.leave();
		  end;
		  //
		  entered := true;
		end
		else
		  dec(giveUp);
		//
	      until (entered or shouldStop or (1 > giveUp));
	      //
	      if (1 > giveUp) then
		inc(f_enterFails);
	    end;
	    //
	    if (not shouldStop and (nothing or (MP3_ERR = res))) then begin
	      // broken stream, re-init MP3
	      f_proto.r_exitMP3(f_MPSTR);
	      f_errorCode := choice(f_proto.r_initMP3(f_MPSTR), 0, mpglib_error_initFail);
	      res := 0;
	    end;
	    //
	    if (MP3_NEED_MORE = res) then
	      size := 0;
	    //
	    if (nothing or (0 = res)) then begin
	      //
	      inc(offset, 16);
	    end;
	  end;
	end;
	//
      end;
    end;
    //
  finally
    //
    //chunkSize := 0;
    mrealloc(chunk);
  end;
  //
  result := 0;
end;

// --  --
function unaMpgLibDecoder.getInDataSize(): unsigned;
begin
  result := f_inStream.getSize();
end;

// --  --
procedure unaMpgLibDecoder.loadLibrary(const libName: string);
begin
  unloadLibrary();
  //
  f_errorCode := loadLib(f_proto, libName);
end;

// --  --
procedure unaMpgLibDecoder.notifyData(data: pointer; size: unsigned; var copyToStream: bool);
var
  new_rate: unsigned;
  new_channels: unsigned;
begin
  new_rate := MPSTR.fr.sampling_frequency;
  new_channels:= MPSTR.fr.stereo;
  //
  if ((f_oldPCM_rate <> new_rate) or (f_oldPCM_channels <> new_channels)) then begin
    //
    notifySamplingChange(freqs[new_rate], 16, new_channels);
    //
    f_oldPCM_rate := new_rate;
    f_oldPCM_channels := new_channels;
  end;
  //
  if (assigned(f_onDataAvail)) then
    f_onDataAvail(self, data, size, copyToStream);
end;

// --  --
procedure unaMpgLibDecoder.notifySamplingChange(rate, bits, channels: unsigned);
begin
  if (assigned(f_onApplySampling)) then
    f_onApplySampling(self, rate, bits, channels);
end;

// --  --
function unaMpgLibDecoder.open(): int;
begin
  start();
  //
  result := 0;
end;

// --  --
procedure unaMpgLibDecoder.startIn();
begin
  inherited;
  //
  f_oldPCM_rate := 0;
  f_oldPCM_channels := 0;
  f_ensureLayer := -1;
  //
  if (0 = f_errorCode) then
    f_errorCode := choice(f_proto.r_initMP3(f_MPSTR), 0, mpglib_error_initFail);
end;

// --  --
procedure unaMpgLibDecoder.startOut();
begin
  inherited;
  //
  if (0 = f_errorCode) then
    f_proto.r_exitMP3(f_MPSTR);
end;

// --  --
procedure unaMpgLibDecoder.unloadLibrary();
begin
  unloadLib(f_proto);
end;

// --  --
procedure unaMpgLibDecoder.write(data: pointer; len: unsigned);
begin
  doWrite(data, len);
end;

initialization
  globalLock := unaInProcessGate.create();

finalization
  freeAndNil(globalLock);

end.

⌨️ 快捷键说明

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