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