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

📄 unaencoderapi.pas

📁 Voice Commnucation Components for Delphi
💻 PAS
📖 第 1 页 / 共 5 页
字号:

      else
	result := BE_ERR_SUCCESSFUL;
    end;
  end;  
  //
  f_inputChunkSize := 1024 * 4;	// just a moderate number of bytes
end;

// --  --
function unaVorbisEnc.loadDLL(): int;
begin
  result := inherited loadDLL();
  //
  if ((0 = result) and vorbis_load_library(cunav_dll_vorbisenc, f_vorbisEncDllPathAndName)) then
  else
    result := -1;
end;

// --  --
procedure unaVorbisEnc.pushPacket(const packet: tOgg_packet);
var
  reqSize: unsigned;
begin
  reqSize := packet.bytes + sizeOf(packet) - sizeOf(pointer);
  //
  if (reqSize > f_outBufSize) then begin
    //
    mrealloc(f_outBuf, reqSize);
    f_outBufSize := reqSize;
  end;
  //
  move(packet.bytes, f_outBuf^, sizeOf(packet) - sizeOf(pointer));
  move(packet.packet^, pArray(f_outBuf)[sizeOf(packet) - sizeOf(pointer)], packet.bytes);
  //
  f_outBufUsed := reqSize;

  // flush packet data
  _write();
end;

// --  --
function unaVorbisEnc.unloadDLL(): int;
begin
  result := inherited unloadDLL();
  //
  vorbis_unload_library(cunav_dll_vorbisenc);
end;

// --  --
procedure unaVorbisEnc.vorbis_addComment(const tagName, tagValue: string);
begin
  vorbis_comment_add_tag(f_vc, pChar(tagName), pChar(tagValue));
end;

// --  --
procedure unaVorbisEnc.vorbis_analyze();
var
  op: tOgg_packet;
begin
  { vorbis does some data preanalysis, then divvies up blocks for
    more involved (potentially parallel) processing.  Get a single block for encoding now }
  while (1 = vorbis_analysis_blockout(f_vd, f_vb)) do begin

    //* analysis, assume we want to use bitrate management */
    try
      vorbis_analysis(f_vb, nil);
      //
      vorbis_bitrate_addblock(f_vb);
    except
    end;  

    while (0 <> vorbis_bitrate_flushpacket(f_vd, op)) do begin
      //
      pushPacket(op);
    end;
  end;
end;

{ unaVorbisDecoder }

// --  --
function unaVorbisDecoder.decode_initBuffer(size: unsigned): int;
begin
  //* OK, got and parsed all three headers. Initialize the Vorbis packet->PCM decoder. */
  result := vorbis_synthesis_init(f_vd, f_vi); //* central decode state */
  if (0 = result) then
    result := vorbis_block_init(f_vd, f_vb);     (* local state for most of the decode so multiple block decodes can proceed in parallel.
						    We could init multiple vorbis_block structures for vd here *)
  //						    
  mrealloc(f_outBuf, size);
  f_outBufSize := size;
  f_outBufSizeInSamples := (size div unsigned(f_vi.channels)) shr 1;
  f_vorbisEos := 0;
end;

// --  --
function unaVorbisDecoder.decode_packet(const packet: tOgg_packet; out wasClipping: bool): int;
var
  i, j: int;
  samples: int;
  pcm: pSingleSamples;
  mono: pSingleArray;
  bout: int;
  val: int;
  consumed: int;
begin
  result := 0;
  //
  if (0 = synthesis_packet(packet)) then //* test for success! */
    synthesis_blockin();
  (*
  **pcm is a multichannel float vector.  In stereo, for
  example, pcm[0] is left, and pcm[1] is right.  samples is
  the size of each channel.  Convert the float values
  (-1.<=range<=1.) to whatever PCM format and write it out *)

  //
  wasClipping := false;
  repeat
    samples := synthesis_pcmout(pcm);
    if (1 > samples) then
      break;
    //
    consumed := 0;
    while (consumed < samples) do begin
      //
      bout := min(unsigned(samples - consumed), f_outBufSizeInSamples);
      //* convert floats to 16 bit signed ints (host order) and interleave */
      i := 0;
      while (i < f_vi.channels) do begin
	//
	mono := pcm[i];
	j := 0;
	while (j < bout) do begin
	  //
	  val := trunc(mono[consumed + j] * 32767);

	  //* optional dither */
	  //int val = val + drand48() - 0.5f;

	  //* might as well guard against clipping */
	  if (val > 32767) then begin
	    //
	    val := 32767;
	    wasClipping := true;
	  end;
	  if (val < -32768) then begin
	    //
	    val := -32768;
	    wasClipping := true;
	  end;
	  //
	  pConvBuffArray(f_outBuf)[i + f_vi.channels * j] := val;
	  inc(j);
	end;
	//
	inc(i);
      end;
      //
      inc(result, bout);
      inc(consumed, bout);
      //
      f_outBufUsed := vi.channels * bout shl 1 {16 bit};
      _write();
    end;
    //
    vorbis_synthesis_read(f_vd, consumed); //* tell libvorbis how  many samples we actually consumed */
    //
  until (false);
end;

// --  --
function unaVorbisDecoder.doClose(): UNA_ENCODER_ERR;
begin
  result := inherited doClose();
end;

// --  --
function unaVorbisDecoder.doEncode(data: pointer; nBytes: unsigned; out bytesUsed: unsigned): UNA_ENCODER_ERR;
var
  res: int;
  clipping: bool;
  og: tOgg_page;
  op: tOgg_packet;
begin
  bytesUsed := 0;	// seems input buffer is not used
  //
  if (nil <> f_oggFile) then begin
    //
    while (0 = f_vorbisEos) do begin
      //
      res := f_oggFile.sync_pageout(og);
      if (0 = res) then
	break; //* need more data */
      //
      if (0 > res) then //* missing or corrupt data at this page position */
	//
	//infoMessage('  corrupt or missing data in bitstream; continuing...')
      else begin
	f_oggFile.stream_pagein(og); //* can safely ignore errors at this point */
	//
	while (true) do begin
	  //
	  res := f_oggFile.stream_packetout(op);
	  if (0 = res) then
	    break; //* need more data */
	  //
	  if (0 > res) then //* missing or corrupt data at this page position */
	    //* no reason to complain; already complained above */
	  else
	    //* we have a packet. decode it */
	    decode_packet(op, clipping);
	end;
	//
	if (0 <> ogg_page_eos(og)) then
	  f_vorbisEos := 1;	// end of page
      end;
    end;
    //
    if (0 = f_vorbisEos) then begin
      //
      // write('  [ ] decoding vorbis stream, page #' + int2str(ogg.os.pageno) + '     '#13);
      if (0 = f_oggFile.sync_blockRead(f_outBufSize)) then
	f_vorbisEos := 1;
    end;
    //
    result := BE_ERR_SUCCESSFUL;
  end
  else
    result := -1;
end;

// --  --
function unaVorbisDecoder.doOpen(): UNA_ENCODER_ERR;
begin
  result := inherited doOpen();
end;

// --  --
function unaVorbisDecoder.doSetConfig(config: pointer): UNA_ENCODER_ERR;
begin
  result := BE_ERR_SUCCESSFUL;
end;

// --  --
{
  Jul 31, 2003 : bug fixed with help of Thomas Schoessow.
  Dec 11, 2003 : yet another bug fixed with help of Jim Margarit.

  -Lake
}
function unaVorbisDecoder.readDecode(buf: pointer; size: unsigned): unsigned;
var
  readSize: unsigned;
  used: unsigned;	// not used :)
begin
  result := 0;
  //
  if ((nil <> buf) and (0 < size) and enter(200)) then begin
    try
      //
      repeat
	//
	readSize := f_outStream.read(@pArray(buf)[result], size - result);
	//
	if (1 > readSize) then
	  doEncode(nil, 0, used)	// decode more data
	else
	  inc(result, readSize);
	//
      until ((result >= size) or (0 <> f_vorbisEos));	// also break if there is no more data!
      //
    finally
      leave();
    end;
  end;
end;

// --  --
function unaVorbisDecoder.synthesis_blockin(): int;
begin
  result := vorbis_synthesis_blockin(f_vd, f_vb);
end;

// --  --
function unaVorbisDecoder.synthesis_packet(const packet: tOgg_packet): int;
begin
  result := vorbis_synthesis(f_vb, packet);
end;

// --  --
function unaVorbisDecoder.synthesis_pcmout(var pcm: pSingleSamples): int;
begin
  result := vorbis_synthesis_pcmout(f_vd, pcm);
end;


{ unaOggFile }

// --  --
procedure unaOggFile.AfterConstruction();
var
  flags: unsigned;
begin
  inherited;
  //
  if (vorbis_load_library(cunav_dll_ogg)) then begin
    f_errorCode := ogg_stream_init(f_os, f_serialno);
    if (0 = f_errorCode) then begin
      if (fileExists(f_fileName)) then
	flags := OPEN_EXISTING
      else
	flags := CREATE_NEW;
      //
      f_fileHandle := Windows.CreateFile(pChar(f_fileName), f_access, FILE_SHARE_READ + FILE_SHARE_WRITE, nil, flags, FILE_ATTRIBUTE_NORMAL, 0);
    end;
  end
  else
    f_errorCode := OV_ERR_NO_DLL_LOADED;
end;

// --  --
procedure unaOggFile.BeforeDestruction();
begin
  inherited;
  //
  ogg_stream_clear(f_os);
  windows.CloseHandle(f_fileHandle);
  //
  vorbis_unload_library(cunav_dll_ogg);
end;

// --  --
constructor unaOggFile.create(const fileName: string; serialno: int; access: unsigned);
begin
  inherited create();
  //
  f_fileName := fileName;
  if (0 > serialno) then begin
    randomize();
    f_serialno := serialno;
  end
  else
    f_serialno := serialno;
  //
  f_access := access;
end;

// --  --
function unaOggFile.flush(): int;
var
  og: tOgg_page;
begin
  if (0 = f_errorCode) then begin
    //
    //* flush all pending data (if any) so new data will start on new page */
    result := 0;
    //
    repeat
      if (0 = ogg_stream_flush(f_os, og)) then
	break;
      //
      writeToFile(f_fileHandle, og.header, og.header_len);
      inc(result, og.header_len);
      //
      writeToFile(f_fileHandle, og.body, og.body_len);
      inc(result, og.body_len);
    until (false);
  end
  else
    result := f_errorCode;
end;

// --  --
function unaOggFile.get_os(): pOgg_stream_state;
begin
  result := @f_os;
end;

// --  --
function unaOggFile.packetIn(const packet: tOgg_packet): int;
begin
  result := ogg_stream_packetin(f_os, packet);
end;

// --  --
function unaOggFile.pageOut(): int;
var
  og: tOgg_page;
begin
  if (0 = f_errorCode) then begin
    //
    //* write out pages (if any) */
    result := 0;
    repeat
      if (0 = ogg_stream_pageout(f_os, og)) then
	break;
      //
      writeToFile(f_fileHandle, og.header, og.header_len);
      inc(result, og.header_len);
      //
      writeToFile(f_fileHandle, og.body, og.body_len);
      inc(result, og.body_len);
    until (false);
  end
  else
    result := f_errorCode;
end;

// --  --
function unaOggFile.stream_packetOut(var op: tOgg_packet): int;
begin
  result := ogg_stream_packetout(f_os, op);
end;

// --  --
function unaOggFile.stream_pagein(const og: tOgg_page): int;
begin
  result := ogg_stream_pagein(f_os, og);
end;

// --  --
function unaOggFile.sync_blockRead(size: unsigned): unsigned;
var
  buffer: pointer;
begin
  //* submit a block to libvorbis' Ogg layer */
  result := size;
  buffer := sync_buffer(result);
  readFromFile(f_fileHandle, buffer, result);
  sync_wrote(result);
end;

// --  --
function unaOggFile.sync_buffer(size: unsigned): pointer;
begin
  result := ogg_sync_buffer(f_oy, size);
end;

// --  --
function unaOggFile.sync_init(): int;
begin
  result := ogg_sync_init(f_oy); //* Now we can read pages */
end;

// --  --
function unaOggFile.sync_pageout(var og: tOgg_page): int;
begin
  result := ogg_sync_pageout(f_oy, og);
end;

// --  --
function unaOggFile.sync_wrote(size: unsigned): int;
begin
  result := ogg_sync_wrote(f_oy, size);
end;

// --  --
function unaOggFile.vorbis_decode_int(decoder: unaVorbisDecoder): int;
var
  i, res: int;
  //
  buffer: pointer;
  readCount: unsigned;
  //
  og: tOgg_page; //* one Ogg bitstream page.  Vorbis packets are inside */
  op: tOgg_packet; //* one raw packet of data for decode */
begin
  //********** Decode setup ************/
  result := -1;
  (* grab some data at the head of the stream.  We want the first page
     (which is guaranteed to be small and onl

⌨️ 快捷键说明

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