📄 u_vcmp3demo_main.pas
字号:
// use lazy thread to return to waveIn ASAP
f_encoder.lazyWrite(data, len);
// or we can use synchronous encode
//f_encoder.encodeChunk(data, len);
end;
end;
// -- --
procedure Tc_form_main.myOnEncoderDataAvail(sender: tObject; data: pointer; size: unsigned; var copyToStream: bool);
var
i: int;
begin
if (nil <> f_encoder) then begin
//
if (f_vorbisEncode = f_encoder) then begin
//
if (nil = f_oggOutFile) then
f_oggOutFile := unaOggFile.create(c_edit_destFile.text, -1, GENERIC_WRITE);
//
if (0 <> f_oggOutFile.errorCode) then begin
c_statusBar_main.panels[1].text := 'OGG library error code: ' + int2str(f_oggOutFile.errorCode);
end
else begin
// care about vorbis header
while (0 < f_vorbisHP) do begin
//
if (f_vorbisEncode.popPacket(f_op)) then begin
f_oggOutFile.packetIn(f_op);
dec(f_vorbisHP);
end
else
break;
//
if (1 > f_vorbisHP) then begin
// This ensures the actual audio data will start on a new page, as per spec
f_oggOutFile.flush();
end;
end;
//
if (1 > f_vorbisHP) then begin // done with header?
// yes
if (f_vorbisEncode.popPacket(f_op)) then begin
//* weld the packet into the bitstream */
f_oggOutFile.packetin(f_op);
f_oggOutFile.pageOut();
end;
end;
end;
//
copyToStream := true; // since we are not writing to file directly here,
// allow oggEncoder to do that for us
//
end
else begin
//
case (f_encoderDestIndex) of
0: begin
// mp3 file does not require any special handling
writeToFile(c_edit_destFile.text, data, size)
end;
1, 2: begin
//
case (f_ipComponentType[tipeEnc]) of
tiptSrv: begin
//
if (0 < f_sockId[tipeEnc]) then begin
//
i := 0;
while (i < int(f_sockClients[tipeEnc].count)) do begin
//
f_socks.sendData(f_sockId[tipeEnc], data, size, unsigned(f_sockClients[tipeEnc][i]));
inc(i);
end;
end;
end;
tiptCln: begin
//
f_socks.sendData(f_sockId[tipeEnc], data, size, f_sockConnId[tipeEnc]);
end;
end; // case
//
copyToStream := false; // since we are not writing to file directly here,
// allow oggEncoder to do that for us
end;
end;
end;
end;
end;
// -- --
procedure Tc_form_main.myOnDecoderDataAvail(sender: tObject; data: pointer; size: unsigned; var copyToStream: bool);
begin
case (f_decoderSourceIndex) of
0: begin
copyToStream := true; // local stream is needed to feed the waveOut
end;
1, 2: begin
// seems like mpgLib has produced new chunk of PCM data
waveOut.write(data, size);
copyToStream := false;
end;
end;
end;
// -- --
procedure Tc_form_main.c_checkBox_enableVBRClick(Sender: TObject);
begin
c_comboBox_minBR.Enabled := (1 = c_comboBox_encoder.ItemIndex) and c_checkBox_enableVBR.Checked;
c_comboBox_maxBR.Enabled := (1 = c_comboBox_encoder.ItemIndex) and c_checkBox_enableVBR.Checked;
c_comboBox_vbrQuality.Enabled := (c_checkBox_enableVBR.Checked and (0 = c_comboBox_avBR.ItemIndex));
//
if (c_checkBox_enableVBR.Checked) then begin
//
c_comboBox_avBR.ItemIndex := 0;
c_comboBox_avBRChange(self);
end
else
c_comboBox_avBR.ItemIndex := 9;
end;
// -- --
procedure Tc_form_main.c_comboBox_encoderChange(Sender: TObject);
var
index: int;
begin
index := c_comboBox_encoder.itemIndex; // 0 - Blade
// 1 - Lame
// 2 - Ogg/Vorbis
//
c_checkBox_enableVBR.enabled := (0 < index);
if (not c_checkBox_enableVBR.Enabled) then
c_checkBox_enableVBR.checked := false;
//
c_checkBox_disBRS.Enabled := (1 = index); // Lame only
//
if (2 = index) then
c_saveDialog_dest.filterIndex := 2
else
c_saveDialog_dest.filterIndex := 1;
//
c_checkBox_copyrighted.enabled := (2 > index);
c_checkBox_original.enabled := (2 > index);
c_checkBox_crc.enabled := (2 > index);
c_checkBox_private.enabled := (2 > index);
end;
// -- --
procedure Tc_form_main.c_comboBox_decoderChange(Sender: TObject);
begin
c_edit_sourceFileChange(self);
end;
// -- --
procedure Tc_form_main.c_comboBox_avBRChange(Sender: TObject);
begin
if ((0 = c_comboBox_avBR.ItemIndex) and not c_checkBox_enableVBR.Checked) then begin
c_comboBox_avBR.ItemIndex := 1;
c_statusBar_main.Panels[1].Text := 'VBR mode must be enabled.';
end;
//
c_comboBox_vbrQuality.Enabled := ((0 = c_comboBox_avBR.ItemIndex) and c_checkBox_enableVBR.Checked);
end;
// -- --
procedure Tc_form_main.c_comboBox_stereoModeChange(Sender: TObject);
begin
if ((2 = c_comboBox_stereoMode.ItemIndex) and not (0 < c_comboBox_encoder.ItemIndex)) then begin
c_comboBox_stereoMode.itemIndex := 1;
c_statusBar_main.panels[1].text := 'Not supported by Blade encoder.';
end;
end;
// -- --
procedure Tc_form_main.c_button_destBrowseClick(Sender: TObject);
begin
if (c_saveDialog_dest.Execute()) then
c_edit_destFile.text := trim(c_saveDialog_dest.fileName);
end;
// -- --
procedure Tc_form_main.c_button_sourceBrowseClick(Sender: TObject);
begin
if (c_openDialog_source.Execute()) then
c_edit_sourceFile.text := trim(c_openDialog_source.fileName);
end;
// -- --
procedure Tc_form_main.c_edit_destFileChange(Sender: TObject);
begin
a_encode_start.enabled := ('' <> trim(c_edit_destFile.text));
c_button_playback.enabled := a_encode_start.enabled;
end;
// -- --
procedure Tc_form_main.c_edit_sourceFileChange(Sender: TObject);
begin
a_decode_start.enabled := not waveOut.active;
//
c_label_warningOgg.visible := (
(0 = c_comboBox_decoder.itemIndex) and
(
not sameString('.ogg', extractFileExt(c_edit_sourceFile.text))
and
(1 > c_comboBox_decoderSource.itemIndex)
)
);
end;
// -- --
procedure Tc_form_main.c_button_playbackClick(Sender: TObject);
begin
shellExecute(handle, 'open', pChar(c_edit_destFile.text), nil, nil, SW_SHOWNORMAL);
end;
// -- --
procedure Tc_form_main.c_button_encCopyrightsClick(Sender: TObject);
begin
c_form_about.doAboutEncode();
end;
// -- --
procedure Tc_form_main.c_checkBox_overwritePClick(Sender: TObject);
begin
if (c_checkBox_overwriteP.checked) then
c_saveDialog_dest.options := c_saveDialog_dest.Options + [ofOverwritePrompt]
else
c_saveDialog_dest.options := c_saveDialog_dest.Options - [ofOverwritePrompt];
end;
// -- --
procedure Tc_form_main.c_comboBox_inputDeviceChange(Sender: TObject);
begin
waveIn.deviceId := c_comboBox_inputDevice.itemIndex - 1;
end;
// -- --
procedure Tc_form_main.c_comboBox_outputDeviceChange(Sender: TObject);
begin
waveOut.deviceId := c_comboBox_outputDevice.itemIndex - 1;
end;
// -- --
procedure Tc_form_main.c_comboBox_encodedDestChange(Sender: TObject);
var
isFile: bool;
isServer: bool;
isClient: bool;
begin
isFile := (0 = c_comboBox_encodedDest.itemIndex);
isServer := (2 = c_comboBox_encodedDest.itemIndex);
isClient := (1 = c_comboBox_encodedDest.itemIndex);
//
c_edit_destFile.visible := isFile;
c_button_destBrowse.visible := isFile;
c_button_playback.visible := isFile;
c_checkBox_overwriteP.visible := isFile;
c_label_encoderMp3File.visible := isFile;
//
c_label_encSrvAddr.visible := isClient;
c_edit_encSrvAddr.visible := isClient;
c_edit_encPortNumber.visible := isServer or isClient;
c_label_encPortNumber.visible := isServer or isClient;
c_label_encType.visible := isServer or isClient;
c_comboBox_encSocketType.visible := isServer or isClient;
end;
// -- --
procedure Tc_form_main.c_comboBox_decoderSourceChange(Sender: TObject);
var
isFile: bool;
isServer: bool;
isClient: bool;
begin
isFile := (0 = c_comboBox_decoderSource.itemIndex);
isClient := (1 = c_comboBox_decoderSource.itemIndex);
isServer := (2 = c_comboBox_decoderSource.itemIndex);
//
c_edit_sourceFile.visible := isFile;
c_button_sourceBrowse.visible := isFile;
c_label_sourceFile.visible := isFile;
//
c_label_decSrvAddr.visible := isClient;
c_edit_decSrvAddr.visible := isClient;
//
c_label_decSrvPort.visible := isClient or isServer;
c_label_decSrvSocketType.visible := isClient or isServer;
c_edit_decSrvPort.visible := isClient or isServer;
c_comboBox_decSrvSocketType.visible := isClient or isServer;
//
if (isClient or isServer) then
c_comboBox_decoder.itemIndex := 2; // only mpgLib is supported as stream decoder as for now
//
c_edit_sourceFileChange(self);
end;
// -- --
procedure Tc_form_main.waveOutFeedChunk(sender: unavclInOutPipe; data: pointer; len: cardinal);
var
realLen: int;
feedLen: unsigned;
//
ok: bool;
begin
case (f_decoderSourceIndex) of
0: begin // file, we have to read data from file and feed waveOut manually
//
if (len > f_feedBufSize) then begin
//
f_feedBufSize := len;
mrealloc(f_feedBuf, f_feedBufSize);
end;
//
feedLen := 0;
ok := (f_mpgOK) or (nil <> f_bassFile) or ((nil <> f_vorbisDecode) and (nil <> f_oggInFile));
//
if (ok) then begin
//
repeat
//
realLen := 0;
case (f_decoderIndex) of
0: begin // vorbis
//
if (nil <> f_vorbisDecode) then begin
//
realLen := f_vorbisDecode.readDecode(f_feedBuf, len - feedLen)
end
end;
1: begin // BASS
//
if (nil <> f_bassFile) then begin
//
realLen := f_bassFile.asChannel.get_data(f_feedBuf, len - feedLen);
if (0 < realLen) then
inc(f_bassDecodedSize, realLen);
//
end;
end;
2: begin // mpgLib
//
if (0 <> f_mpgFile) then begin
//
realLen := f_mpgDecoder.f_outStream.getSize();
if (realLen < int(len - feedLen)) then begin
//
repeat
// feed more data to encoder
realLen := f_feedBufSize;
readFromFile(f_mpgFile, f_feedBuf, unsigned(realLen));
if (0 < realLen) then
f_mpgDecoder.write(f_feedBuf, realLen)
else
break; // no more data
//
while (not f_mpgDecoder.shouldStop and (f_mpgDecoder.inDataSize > 0) and (f_mpgDecoder.f_outStream.getSize() < 1)) do
sleep(10);
//
until (f_mpgDecoder.shouldStop or (f_mpgDecoder.f_outStream.getSize() > 0));
end;
//
if (0 < realLen) then
realLen := f_mpgDecoder.f_outStream.read(f_feedBuf, len - feedLen);
//
end
end;
end; // case
//
if (0 < realLen) then begin
//
// since decoder returns PCM samples, we can feed them directly to waveOut
if (not f_mpgNeedFormatUpdate) then
waveOut.write(f_feedBuf, realLen);
//
inc(feedLen, realLen);
end;
//
until ((1 > realLen) or (feedLen >= len));
//
// check if we have reached end of the file
if (0 >= realLen) then
a_decode_stop.execute();
//
end
else
a_decode_stop.execute();
//
end;
1, 2: begin // TCP/IP stream
//
case (f_decoderIndex) of
0: begin // vorbis
// not supported
end;
1: begin // BASS
// not supported
end;
2: begin // mpgLib
// we will feed waveOut as soon as decoder has some new data in myOnDecoderDataAvail(), so nothing to do here
end;
end; // case (f_decoderIndex)
end;
end;
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -