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

📄 u_vcwaveplayer_main.pas

📁 Voice Commnucation Components for Delphi
💻 PAS
字号:

(*
	----------------------------------------------

	  u_vcWavePlayer_main.pas
	  Voice Communicator components version 2.5 Pro
	  VC Wave Player Demo application - main form

	----------------------------------------------
	  This source code cannot be used without
	  proper license granted to you as a private
	  person or an entity by the Lake of Soft, Ltd

	  Visit http://lakeofsoft.com/ for more information.

	  Copyright (c) 2001, 2007 Lake of Soft, Ltd
		     All rights reserved
	----------------------------------------------

	  created by:
		Lake, 23 Oct 2002

	  modified by:
		Lake, Oct 2002
		Lake, Feb-May 2003
		Lake, Oct 2005
		Lake, Apr 2007

	----------------------------------------------
*)

{$I unaDef.inc}

unit
  u_vcWavePlayer_main;

interface

uses
  Windows, unaTypes, unaClasses,
  Forms, Messages, ComCtrls, Classes, ActnList, Dialogs, StdCtrls,
  ExtCtrls, Controls, unavcIDE;

type
  Tc_form_main = class(TForm)
    wavIn: TunavclWaveRiff;
    waveResampler: TunavclWaveResampler;
    waveOut: TunavclWaveOutDevice;
    c_openDialog_main: TOpenDialog;
    c_statusBar_main: TStatusBar;
    c_timer_update: TTimer;
    c_panel_top: TPanel;
    c_edit_fileName: TEdit;
    Label1: TLabel;
    Bevel1: TBevel;
    c_label_caption: TLabel;
    c_button_browse: TButton;
    c_actionList_main: TActionList;
    a_file_open: TAction;
    a_playback_start: TAction;
    a_playback_stop: TAction;
    c_trackBar_pos: TTrackBar;
    c_button_start: TButton;
    c_button_stop: TButton;
    c_trackBar_tempo: TTrackBar;
    c_checkBox_autoRewind: TCheckBox;
    c_paintBox_wave: TPaintBox;
    c_label_tempo: TLabel;
    c_checkBox_enableGO: TCheckBox;
    c_go_update: TTimer;
    c_trackBar_volume: TTrackBar;
    c_label_vol: TLabel;
    c_progressBar_volumeLeft: TProgressBar;
    Bevel2: TBevel;
    c_progressBar_volumeRight: TProgressBar;
    Bevel3: TBevel;
    Label2: TLabel;
    c_button_pause: TButton;
    a_playback_pause: TAction;
    a_playback_resume: TAction;
    c_button_resume: TButton;
    //
    procedure formCreate(sender: tObject);
    procedure formDestroy(sender: tObject);
    procedure formShow(sender: tObject);
    procedure formCloseQuery(sender: tObject; var canClose: boolean);
    //
    procedure a_file_openExecute(Sender: TObject);
    procedure a_playback_startExecute(Sender: TObject);
    procedure a_playback_stopExecute(Sender: TObject);
    //
    procedure c_edit_fileNameChange(Sender: TObject);
    procedure c_timer_updateTimer(Sender: TObject);
    procedure c_checkBox_autoRewindClick(Sender: TObject);
    procedure c_trackBar_posChange(Sender: TObject);
    procedure c_paintBox_wavePaint(Sender: TObject);
    procedure c_trackBar_tempoChange(Sender: TObject);
    procedure c_label_captionClick(Sender: TObject);
    procedure c_go_updateTimer(Sender: TObject);
    procedure c_trackBar_volumeChange(Sender: TObject);
    //
    procedure waveOutFeedChunk(sender: unavclInOutPipe; data: pointer; len: cardinal);
    procedure wavInStreamIsDone(sender: TObject);
    procedure a_playback_pauseExecute(Sender: TObject);
    procedure a_playback_resumeExecute(Sender: TObject);
    procedure c_statusBar_mainClick(Sender: TObject);
  private
    { Private declarations }
    f_config: unaIniFile;
    f_autoSeekPos: bool;
    f_samples: array[word] of smallInt;
    f_samplesCount: unsigned;
    f_oldTempo: unsigned;
    f_invalidateIsDone: bool;
    f_inTimer: bool;
    f_inTimerGO: bool;
    f_wavReadIsDone: bool;
    f_posDisplayMode: int;
    //
    procedure reEnableControls(isOpen: bool);
  public
    { Public declarations }
  end;

var
  c_form_main: Tc_form_main;


implementation


{$R *.dfm}

uses
  unaUtils, unaVCLUtils, unaWave,
  Graphics, CommCtrl, ShellAPI;

// --  --
procedure Tc_form_main.formCreate(sender: tObject);
begin
  f_config := unaIniFile.create();
end;

// --  --
procedure Tc_form_main.formDestroy(sender: tObject);
begin
  freeAndNil(f_config);
end;

// --  --
procedure Tc_form_main.formShow(sender: tObject);
begin
  loadControlPosition(self, f_config);
  //
  reEnableControls(false);
  c_edit_fileName.text := f_config.get('gui.file.name', '');
  c_checkBox_enableGO.checked := f_config.get('gui.go.checked', true);
  c_checkBox_autoRewind.checked := f_config.get('gui.ar.checked', false);
  //
  c_edit_fileNameChange(self);
  //
  c_paintBox_wave.ControlStyle := c_paintBox_wave.ControlStyle + [csOpaque];
  //
  f_invalidateIsDone := true;
end;

// --  --
procedure Tc_form_main.formCloseQuery(sender: tObject; var canClose: boolean);
begin
  c_timer_update.enabled := false;
  c_go_update.enabled := false;
  //
  a_playback_stop.execute();
  //
  saveControlPosition(self, f_config);
  //
  f_config.setValue('gui.file.name', c_edit_fileName.text);
  f_config.setValue('gui.go.checked', c_checkBox_enableGO.checked);
  f_config.setValue('gui.ar.checked', c_checkBox_autoRewind.checked);
end;

// --  --
procedure Tc_form_main.reEnableControls(isOpen: bool);
begin
  a_playback_start.enabled := not isOpen;
  a_playback_stop.enabled := isOpen;
  //
  c_edit_fileName.enabled := not isOpen;
  c_trackBar_pos.enabled := isOpen;
  //
  if (not c_trackBar_pos.enabled) then
    wavIn.waveStream.streamPosition := 0;
  //
  c_trackBar_tempo.enabled := isOpen;
end;

// --  --
procedure Tc_form_main.a_file_openExecute(Sender: TObject);
begin
  if (c_openDialog_main.execute()) then begin
    //
    c_edit_fileName.text := c_openDialog_main.fileName;
    if (not wavIn.active) then begin
      //
      wavIn.fileName := c_edit_fileName.text;
      c_statusBar_main.panels[1].text := wavIn.waveStream.srcFormatInfo;
    end;
    //
    waveResampler.resampler.priority := THREAD_PRIORITY_TIME_CRITICAL; 	// die CPU stress!
  end;
end;

// --  --
procedure Tc_form_main.c_edit_fileNameChange(Sender: TObject);
begin
  a_playback_start.enabled := not wavIn.active and (fileExists(trim(c_edit_fileName.text)));
end;

// --  --
procedure Tc_form_main.c_timer_updateTimer(Sender: TObject);
var
  bytesPerSec: double;
  bytesRateRatio: double;
  codecRatio: double;
  msec: unsigned;
  msecTotal: unsigned;
begin
  if (not (csDestroying in componentState) and not f_inTimer) then begin
    //
    f_inTimer := true;
    try
      c_statusBar_main.panels[0].text := int2str(ams() shr 10, 10, 3) + ' KB';
      //
      with (wavIn) do begin
	//
	f_autoSeekPos := true;
	try
	  c_trackBar_pos.position := percent(waveStream.streamPosition, waveStream.streamSize);
	finally
	  f_autoSeekPos := false;
	end;
	//
	case (f_posDisplayMode) of

	  0: // bytes
	    c_statusBar_main.panels[2].text := int2str(waveStream.streamPosition, 10, 3, '`') + ' / ' + int2str(waveStream.streamSize, 10, 3, '`');

	  1: begin // time
	    //
	    if (nil <> waveStream.codec) then
	      codecRatio := waveStream.codec.dstChunkSize / waveStream.codec.chunkSize
	    else
	      codecRatio := 1;
	    //
	    bytesPerSec := (waveResampler.pcm_SamplesPerSec *
			    waveResampler.pcm_BitsPerSample *
			    waveResampler.pcm_NumChannels) shr 3;
	    //		    
	    bytesRateRatio := ((waveResampler.resampler.dstFormat.nSamplesPerSec *
				waveResampler.resampler.dstFormat.wBitsPerSample *
				waveResampler.resampler.dstFormat.nChannels) shr 3)
				/
			       ((waveOut.pcm_SamplesPerSec *
				 waveOut.pcm_BitsPerSample *
				 waveOut.pcm_NumChannels) shr 3);
	    //
	    bytesPerSec := bytesPerSec / (codecRatio * bytesRateRatio);
	    //
	    if (0 < bytesPerSec) then begin
	      //
	      msec := trunc(waveStream.streamPosition / bytesPerSec * 1000);
	      msecTotal := trunc(waveStream.streamSize / bytesPerSec * 1000);
	    end
	    else begin
	      //
	      msec := 0;
	      msecTotal := 0;
	    end;
	    //
	    c_statusBar_main.panels[2].text := int2str(trunc(msec), 10, 3) + ' / ' + int2str(trunc(msecTotal), 10, 3);
	  end;

	  else
	    c_statusBar_main.panels[2].text := 'Unknown display mode';

	end;
      end;
      //
      if (f_wavReadIsDone and (waveResampler.resampler.chunkSize > waveResampler.availableDataLenIn)) then
	a_playback_stop.execute();
      //
    finally
      f_inTimer := false;
    end;
  end;
end;

// --  --
procedure Tc_form_main.a_playback_startExecute(Sender: TObject);
begin
  wavIn.fileName := c_edit_fileName.Text;
  //
  c_statusBar_main.panels[1].text := wavIn.waveStream.srcFormatInfo;
  c_statusBar_main.hint := wavIn.waveStream.srcFormatInfo;
  //
  f_wavReadIsDone := false;
  wavIn.open();
  //
  reEnableControls(true);
end;

// --  --
procedure Tc_form_main.a_playback_stopExecute(Sender: TObject);
begin
  wavIn.close();
  //
  reEnableControls(false);
  //
  c_trackBar_tempo.position := 10;
  c_trackBar_volume.position := 10;
end;

// --  --
procedure Tc_form_main.c_checkBox_autoRewindClick(Sender: TObject);
begin
  wavIn.loop := c_checkBox_autoRewind.checked;
end;

// --  --
procedure Tc_form_main.c_trackBar_posChange(Sender: TObject);
var
  pos: unsigned;
begin
  if (not f_autoSeekPos) then begin
    //
    pos := (wavIn.waveStream.streamSize div 100) * unsigned(c_trackBar_pos.position);
    wavIn.waveStream.streamPosition := pos;
  end;
end;

// --  --
procedure Tc_form_main.c_paintBox_wavePaint(Sender: TObject);
var
  stepV: double;
  offsetV: double;

  procedure renderDisplay(startOffset: unsigned);
  var
    i: unsigned;
    pos: unsigned;
  begin
    if (1 < f_samplesCount) then begin
      //
      with (c_paintBox_wave) do begin
	pos := 0;
	canvas.moveTo(0, trunc(offsetV - f_samples[startOffset] * stepV));
	//
	i := startOffset + 1;
	while (i < f_samplesCount - 1) do begin
	  //
	  canvas.lineTo(pos, trunc(offsetV - f_samples[i] * stepV));
	  //
	  inc(pos);
	  inc(i, 2);
	end;
      end;
    end;
  end;

begin
  with (c_paintBox_wave) do begin
    //
    canvas.brush.color := clBtnFace;
    canvas.fillRect(getClientRect);
    //
    if (0 < f_samplesCount) then begin
      //
      stepV := height / $10000;
      offsetV := height / 1.99;
      // left
      canvas.pen.color := clBlue;
      renderDisplay(0);
      // right
      canvas.pen.color := clRed;
      renderDisplay(1);
    end;
    //
    f_invalidateIsDone := true;
  end;
end;

// --  --
procedure Tc_form_main.c_trackBar_tempoChange(Sender: TObject);
var
  pos: unsigned;
  rate: unsigned;
begin
  if (f_oldTempo <> unsigned(c_trackBar_tempo.Position)) then begin
    //
    f_oldTempo := c_trackBar_tempo.position;
    //
    // 08 Apr, 2004: Lake
    // more correct tempo chnage calculations
    // thanks to Tim Mahler for poiting on this problem
    //
    pos := (c_trackBar_tempo.max - c_trackBar_tempo.position) * 10;	// 0% .. 100% .. 200%
    if (1 > pos) then
      pos := 10;	// 10% instead of 0%
    //
    rate := (44100 * 100) div pos;
    waveResampler.resampler.setSampling(false, rate, 16, 2);
    wavIn.waveStream.realTimer.interval := ((1000 div wavIn.waveStream.chunkPerSecond) * 100) div pos;
    //
    c_label_tempo.caption := int2str(pos) + '%';
  end;
end;

// --  --
procedure Tc_form_main.c_label_captionClick(Sender: TObject);
begin
  shellExecute(handle, 'open', 'http://lakeofsoft.com/vc', nil, nil, SW_SHOWNORMAL);
end;

// --  --
procedure Tc_form_main.c_go_updateTimer(Sender: TObject);
begin
  if (not (csDestroying in componentState)) then begin
    //
    if (not f_inTimerGO) then begin
      //
      f_inTimerGO := true;
      try
	if (not f_invalidateIsDone) then begin
	  //
	  if (c_checkBox_enableGO.checked) then
	    c_paintBox_wave.invalidate();
	end;    
	//
	c_progressBar_volumeLeft.position := waveGetLogVolume(waveResampler.resampler.getVolume(0));
	c_progressBar_volumeRight.position := waveGetLogVolume(waveResampler.resampler.getVolume(1));
      finally
	f_inTimerGO := false;
      end;
    end;
  end;
end;

// --  --
procedure Tc_form_main.c_trackBar_volumeChange(Sender: TObject);
var
  pos: int;
begin
  pos := c_trackBar_volume.max - c_trackBar_volume.position;
  waveResampler.resampler.setVolume(-1, pos * 100);
  c_label_vol.caption := int2str(pos * 10) + '%';
end;

// --  --
procedure Tc_form_main.waveOutFeedChunk(sender: unavclInOutPipe; data: pointer; len: cardinal);
begin
  if (not (csDestroying in componentState)) then begin
    //
    if (f_invalidateIsDone) then begin
      //
      move(data^, f_samples, len);
      f_samplesCount := len shr 2;	{ 16 bits; 2 channels }
      f_invalidateIsDone := false;
    end;
  end;
end;

// --  --
procedure Tc_form_main.wavInStreamIsDone(sender: TObject);
begin
  f_wavReadIsDone := true;
end;

// --  --
procedure Tc_form_main.a_playback_pauseExecute(Sender: TObject);
begin
  wavIn.waveStream.realTimer.stop();
  wavIn.waveStream.pause();
end;

// --  --
procedure Tc_form_main.a_playback_resumeExecute(Sender: TObject);
begin
  wavIn.waveStream.resume();
  wavIn.waveStream.realTimer.start();
end;

// --  --
procedure Tc_form_main.c_statusBar_mainClick(Sender: TObject);
begin
  // toggle time/pos display
  inc(f_posDisplayMode);
  //
  if (1 < f_posDisplayMode) then
    f_posDisplayMode := 0;
end;


end.

⌨️ 快捷键说明

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