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

📄 unaencoderapi.pas

📁 Voice Commnucation Components for Delphi
💻 PAS
📖 第 1 页 / 共 5 页
字号:
      //
      doOpen();
      //
      f_opened := true;
      //
      f_lazyThread.start();
    end;
    result := BE_ERR_SUCCESSFUL;
  end
  else
    result := UNA_ENCODER_ERR_CONFIG_REQUIRED;
  //
  f_errorCode := result;
end;

// --  --
function unaAbstractEncoder.read(buf: pointer; size: unsigned): unsigned;
begin
  result := f_outStream.read(buf, size);
end;

// --  --
function unaAbstractEncoder.setConfig(config: pointer): UNA_ENCODER_ERR;
begin
  close();	// make sure stream is closed
  //
  result := doSetConfig(config);
  if (BE_ERR_SUCCESSFUL = result) then begin
    //
    if (f_outBufSize < f_minOutputBufSize) then begin
      //
      mrealloc(f_outBuf, f_minOutputBufSize);
      f_outBufSize := f_minOutputBufSize;
    end;
  end;
  //
  f_errorCode := result;
  f_configOK := (BE_ERR_SUCCESSFUL = result);
end;

// --  --
procedure unaAbstractEncoder.set_priority(value: integer);
begin
  f_lazyThread.priority := value;
end;

// --  --
procedure unaAbstractEncoder._write();
begin
  if (0 < f_outBufUsed) then begin
    //
    inc(f_encodedDataSize, f_outBufUsed);
    //
    if (doDAEvent(f_outBuf, f_outBufUsed)) then
      f_outStream.write(f_outBuf, f_outBufUsed);
    //
    f_outBufUsed := 0;
  end;
end;

{ unaBladeMp3Enc }

// --  --
procedure unaBladeMp3Enc.AfterConstruction();
begin
  inherited;
  //
  new(f_version);
  f_stream := $FFFFFFFF;
  //
  if (0 = loadDll()) then
    f_errorCode := BE_ERR_SUCCESSFUL
  else
    f_errorCode := UNA_ENCODER_ERR_NO_DLL;
  //
  if (BE_ERR_SUCCESSFUL = errorCode) then
    getVersion();
end;

// --  --
procedure unaBladeMp3Enc.BeforeDestruction();
begin
  inherited;
  //
  dispose(f_version);
  //
  unloadDll();
end;

// --  --
constructor unaBladeMp3Enc.create(const dllPathAndName: string; priority: integer);
begin
  inherited create(priority);
  //
  f_dllPathAndName := dllPathAndName;
end;

// --  --
function unaBladeMp3Enc.doClose(): UNA_ENCODER_ERR;
begin
  result := beDeinitStream(f_bladeProc, f_stream, f_outBuf, f_outBufUsed);
  //
  if (BE_ERR_SUCCESSFUL = result) then
    result := beCloseStream(f_bladeProc, f_stream);
  //
  f_stream := $FFFFFFFF;
end;

// --  --
function unaBladeMp3Enc.doEncode(data: pointer; nBytes: unsigned; out bytesUsed: unsigned): UNA_ENCODER_ERR;
begin
  result := beEncodeChunk(f_bladeProc, f_stream, nBytes shr 1 {16 bits; regardless of number of channels}, data, f_outBuf, f_outBufUsed);
  bytesUsed := nBytes;	// I hope so	
end;

// --  --
function unaBladeMp3Enc.doOpen: UNA_ENCODER_ERR;
begin
  // blade has no openStream()
  result := BE_ERR_SUCCESSFUL;
end;

// --  --
function unaBladeMp3Enc.doSetConfig(config: pointer): UNA_ENCODER_ERR;
var
  nSamples: unsigned;
begin
  result := beInitStream(f_bladeProc, config, nSamples, f_minOutputBufSize, f_stream);
  //
  // -- all samples are 2 bytes long, regadless is it mono/stereo --
  //
  f_inputChunkSize := nSamples shl 1 {* f_sampleSize};
end;

// --  --
procedure unaBladeMp3Enc.getVersion();
begin
  beVersion(f_bladeProc, f_version^);
end;

// --  --
function unaBladeMp3Enc.loadDLL(): int;
begin
  result := blade_loadDLL(f_bladeProc, f_dllPathAndName);
end;

// --  --
function unaBladeMp3Enc.unloadDLL(): int;
begin
  result := blade_unloadDLL(f_bladeProc);
end;

{ unaLameMp3Enc }

// --  --
function unaLameMp3Enc.doClose(): UNA_ENCODER_ERR;
begin
  result := lameDeinitStream(f_lameProc, f_stream, f_outBuf, f_outBufUsed);
  //
  if (BE_ERR_SUCCESSFUL = result) then begin
    //
    // work around for stupid lame DLL bug
    lameWriteVBRHeader(f_lameProc, '');
    //
    //
    result := lameCloseStream(f_lameProc, f_stream);
  end;
  //
  f_stream := $FFFFFFFF;
end;

// --  --
function unaLameMp3Enc.doEncode(data: pointer; nBytes: unsigned; out bytesUsed: unsigned): UNA_ENCODER_ERR;
begin
  result := lameEncodeChunk(f_lameProc, f_stream, nBytes shr 1 {16 bits; regardless of number of channels}, data, f_outBuf, f_outBufUsed);
  bytesUsed := nBytes;	// I hope so
end;

// --  --
function unaLameMp3Enc.doSetConfig(config: pointer): UNA_ENCODER_ERR;
var
  nSamples: unsigned;
begin
  result := lameInitStream(f_lameProc, PBE_CONFIG_FORMATLAME(config), nSamples, f_minOutputBufSize, f_stream);
  //
  // -- all samples are 2 bytes long, regadless is it mono/stereo --
  //
  f_inputChunkSize := nSamples shl 1 {* f_sampleSize};
end;

// --  --
procedure unaLameMp3Enc.getVersion();
begin
  lameVersion(f_lameProc, f_version^);
end;

// --  --
function unaLameMp3Enc.loadDLL(): int;
begin
  result := lame_loadDLL(f_lameProc, f_dllPathAndName);
end;

// --  --
function unaLameMp3Enc.unloadDLL(): int;
begin
  result := lame_unloadDLL(f_lameProc);
end;

{ unaVorbisAbstract }

// --  --
procedure unaVorbisAbstract.AfterConstruction();
begin
  inherited;
  //
  f_popPacketBuf := nil;
  f_popPacketBufSize := 0;
  //
  if (0 = loadDll()) then
    f_errorCode := BE_ERR_SUCCESSFUL
  else
    f_errorCode := UNA_ENCODER_ERR_NO_DLL;
end;

// --  --
procedure unaVorbisAbstract.BeforeDestruction();
begin
  inherited;
  //
  mrealloc(f_popPacketBuf);
  //
  unloadDll();
end;

// --  --
constructor unaVorbisAbstract.create(const vorbisDll: string; priority: integer);
begin
  inherited create(priority);
  //
  f_vorbisDllPathAndName := vorbisDll;
  f_priority := priority;
end;

// --  --
function unaVorbisAbstract.doClose(): UNA_ENCODER_ERR;
begin
  vorbis_block_clear(f_vb);
  vorbis_dsp_clear(f_vd);
  vorbis_comment_clear(f_vc);
  vorbis_info_clear(f_vi);
  //
  result := BE_ERR_SUCCESSFUL;
end;

// --  --
function unaVorbisAbstract.doPopPacket(var packet: tOgg_packet): bool;
begin
  if (f_outStream.getAvailableSize() >= sizeOf(packet) - sizeOf(pointer)) then begin
    //
    f_outStream.read(@packet.bytes, sizeOf(packet) - sizeOf(pointer));
    if (0 < packet.bytes) then begin
      //
      if (unsigned(packet.bytes) > f_popPacketBufSize) then begin
	mrealloc(f_popPacketBuf, packet.bytes);
	f_popPacketBufSize := packet.bytes;
      end;
      //
      packet.packet := f_popPacketBuf;
      packet.bytes := f_outStream.read(packet.packet, packet.bytes, true);
    end
    else
      packet.packet := nil;
    //
    result := true;
  end
  else
    result := false;
end;

// --  --
function unaVorbisAbstract.get_vb(): pVorbis_block;
begin
  result := @f_vb;
end;

// --  --
function unaVorbisAbstract.get_vc(): pVorbis_comment;
begin
  result := @f_vc;
end;

// --  --
function unaVorbisAbstract.get_vd(): pVorbis_dsp_state;
begin
  result := @f_vd;
end;

// --  --
function unaVorbisAbstract.get_vi(): pVorbis_info;
begin
  result := @f_vi;
end;

// --  --
function unaVorbisAbstract.loadDLL(): int;
begin
  if (vorbis_load_library(cunav_dll_vorbis, f_vorbisDllPathAndName)) then begin
    //
    vorbis_info_init(f_vi);
    //
    f_version := f_vi.version;
    result := BE_ERR_SUCCESSFUL;
  end
  else
    result := -1;
end;

// --  --
function unaVorbisAbstract.popPacket(var packet: tOgg_packet): bool;
begin
  result := doPopPacket(packet);
end;

// --  --
function unaVorbisAbstract.unloadDLL(): int;
begin
  vorbis_unload_library(cunav_dll_vorbis);
  result := 1;
end;

{ unaVorbisEnc }

// --  --
constructor unaVorbisEnc.create(const vorbisDll, vorbisEncDll: string; priority: integer);
begin
  inherited create(vorbisDll, priority);
  //
  f_vorbisEncDllPathAndName := vorbisEncDll;
end;

// --  --
function unaVorbisEnc.doClose(): UNA_ENCODER_ERR;
begin
  if (not f_isLastChunk) then begin
    //
    f_isLastChunk := true;
    //
    { End of file. This can be done implicitly in the mainline, but it's easier to see here in non-clever fashion.
      Tell the library we're at end of stream so that it can handle the last frame and mark end of stream in the output properly
    }
    result := vorbis_analysis_wrote(f_vd, 0);
    //
    vorbis_analyze();
    //
    inherited doClose();
  end
  else
    result := BE_ERR_SUCCESSFUL;
  //
end;

// --  --
function unaVorbisEnc.doEncode(data: pointer; nBytes: unsigned; out bytesUsed: unsigned): UNA_ENCODER_ERR;
var
  i, j: int;
  nSamples: int;
  buf: pSingleSamples;
  psia: pSmallInt;
  //
  header: tOgg_packet;
  header_comm: tOgg_packet;
  header_code: tOgg_packet;
begin
  bytesUsed := 0;
  //
  if (f_isFirstChunk) then begin
    //
    //* set up our packet->stream encoder */

    { Vorbis streams begin with three headers; the initial header (with
      most of the codec setup parameters) which is mandated by the Ogg
      bitstream spec.  The second header holds any comment fields.  The
      third header holds the bitstream codebook.  We merely need to
      make the headers, then pass them to libvorbis one at a time;
      libvorbis handles the additional Ogg bitstream constraints
    }
    vorbis_analysis_headerout(f_vd, f_vc, header, header_comm, header_code);
    pushPacket(header);
    pushPacket(header_comm);
    pushPacket(header_code);
    //
    f_isFirstChunk := false;
  end;
  //
  if (0 < nBytes) then begin
    //
    nSamples := (nBytes div unsigned(f_vi.channels)) shr 1 { 16 bit };
    //
    //* expose the buffer to submit data */
    buf := vorbis_analysis_buffer(f_vd, nSamples);
    //
    //* uninterleave samples */
    i := 0;
    psia := data;
    while (i < nSamples) do begin
      //
      for j := 0 to f_vi.channels - 1 do begin
	//
	{ old ugly code

	buf[j][i] := smallInt( (pArray(data)[i shl f_vi.channels + j shl 1 + 1] shl 8) or
				pArray(data)[i shl f_vi.channels + j shl 1 + 0]
			     ) / 32768;
	}
	//
	buf[j][i] := psia^ / 32768;
	//
	inc(psia);
      end;
      //
      inc(i);
    end;
    //
    //* tell the library how much we actually submitted */
    result := vorbis_analysis_wrote(f_vd, nSamples);
    //
    bytesUsed := nBytes;	// looks so
    //
    vorbis_analyze();
  end
  else
    result := BE_ERR_SUCCESSFUL;
end;

// --  --
function unaVorbisEnc.doOpen(): UNA_ENCODER_ERR;
begin
  result := vorbis_analysis_init(f_vd, f_vi);
  if (0 = result) then
    result := vorbis_block_init(f_vd, f_vb);
  if (0 = result) then
    vorbis_comment_init(f_vc);
  //
  f_isFirstChunk := true;
  f_isLastChunk := false;
end;

// --  --
function unaVorbisEnc.doSetConfig(config: pointer): UNA_ENCODER_ERR;
begin
  vorbis_info_clear(f_vi);
  vorbis_info_init(f_vi);
  //
  with pVorbisSetup(config)^ do begin
    //
    case (r_encodeMethod) of

      vemABR: begin
	//
	result := vorbis_encode_init(f_vi, r_numOfChannels, r_samplingRate, r_max_bitrate, r_normal_bitrate, r_min_bitrate);
      end;

      vemVBR: begin
	//
	result := vorbis_encode_init_vbr(f_vi, r_numOfChannels, r_samplingRate, r_quality);
      end;

      vemRateManage: begin
	//
	result := vorbis_encode_setup_managed(f_vi, r_numOfChannels, r_samplingRate, r_manage_maxBitrate, r_manage_normalBitrate, r_manage_minBitrate) or
		  vorbis_encode_ctl(f_vi, r_manage_mode, nil) or
		  vorbis_encode_setup_init(f_vi);
      end;

⌨️ 快捷键说明

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