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

📄 u_vcmp3demo_main.pas

📁 Voice Commnucation Components for Delphi
💻 PAS
📖 第 1 页 / 共 4 页
字号:
    // 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 + -