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