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

📄 wav2mp3.dpr

📁 Voice Commnucation Components for Delphi
💻 DPR
字号:

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

	  wav2mp3.dpr
	  Voice Communicator components version 2.5
	  WAV to MP3 stream encoder example

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

	  Visit http://lakeofsoft.com/ for details.

	  Copyright (c) 2002-2005 Lake of Soft, Ltd
		     All rights reserved
	----------------------------------------------

	  created by:
		Lake, 24 Oct 2002

	  modified by:
		Lake, Oct 2002
		Lake, Nov 2002
		Lake, Jun 2003
		Lake, Oct 2005

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

{$APPTYPE CONSOLE}
{$DEFINE CONSOLE}

{$I unaDef.inc}

program
  wav2mp3;

uses
  Windows, unaTypes, unaUtils, unaClasses,
{$IFDEF VCX_DEMO }
  SysUtils,
{$ENDIF}
  unaMsAcmClasses, unaBladeEncAPI, unaEncoderAPI;


// -- globals --

var
  encoder: unaAbstractEncoder;			// encoder module
  acm: unaMsAcm;				// acm manager for WAVe reader
  waveReader: unaRiffStream;			// WAVe reader
  waveResampler: unaWaveResampler;		// resampler
  mp3File: string;				// name of target MP3 file
  feedBuffer: array[0..$1FFFF] of byte;		// lower size will give better end-user output, but reduce the performance

// --  --
procedure done();
begin
  infoMessage('* Terminating, please wait..');
  freeAndNil(encoder);
  freeAndNil(waveReader);
  freeAndNil(waveResampler);
  freeAndNil(acm);
  infoMessage('Have a nice OS.');
end;

// -- initialization --
function init(): bool;
var
  config: unaIniFile;
  encoderModel: unsigned;
  encoderModule: string;
  // encoder config
  bladeConfig: BE_CONFIG;
  lameConfig: BE_CONFIG_FORMATLAME;
  mp3Config: pointer;
  minBR, maxBR: unsigned;
  samplesRate: unsigned;
  stereoMode: int;
begin
  acm := unaMsAcm.create();
  acm.enumDrivers();
  //
  config := unaIniFile.create();

  // check input file
  result := false;
  infoMessage('* Checking input file: ' + paramStr(1) + ', please wait..');
  if (fileExists(paramStr(1))) then begin
    //
    waveReader := unaRiffStream.create(paramStr(1), false, false, acm);
    case (waveReader.status) of
      0: begin
	 infoMessage('  WAV file correct, stream format is ' + format2str(waveReader.srcFormat^));
	 result := true;
      end;	 
      -1: infoMessage('  File is not a valid RIF file.');
      -2: infoMessage('  File is valid RIF file, but is not a valid WAVe file.');
      -3: infoMessage('  No Acm was specified (but it is required for conversion).');
      -4: infoMessage('  Unknown driver for WAVe file (cannot locate MS ACM driver).');
      -5: infoMessage('  Unknown WAVe format (for selected MS ACM driver).');
      else
	  infoMessage('  Unknown error when reading input file.');
    end;
    //
    if (result) then begin
      // create resampler device
      waveResampler := unaWaveResampler.create(false);
      // link wave to resampler
      waveReader.addConsumer(waveResampler);
      // do not care about input/output stream overloading
      with (waveResampler) do begin
	//
	overNumIn := 0;
	overNumOut := 0;
	// assign sampling params
	setSampling(true, waveReader.dstFormat^);
	setSampling(false,
	  config.get('target.pcm.sps', unsigned(44100)),
	  16,	// mp3 always has 16 bits
	  choice(1 = config.get('target.pcm.stereo', unsigned(1)), unsigned(2), 1));
      end;	  
      //
      infoMessage('  File has been successfully opened.');
    end;
  end
  else
    infoMessage('  File cannot be opened, terminating..');

  // check output file
  if (result) then begin
    //
    if (1 < paramCount) then
      mp3File := paramStr(2)
    else
      mp3File := changeFileExtW(paramStr(1), '.mp3');
    //
    if (fileExists(mp3File)) then begin
      infoMessage('* Output file [' + mp3file + '] already exists, terminating..');
      result := false;
    end
    else
      infoMessage('* Output file [' + mp3file + '] has been successfully initialized.');
  end;

  // check encoder
  if (result) then begin
    //
    encoderModel := config.get('encoder.model', unsigned(0));
    encoderModule := config.get('encoder.module', '');
    case (encoderModel) of
      1: begin
	infoMessage('* Using Blade encoder');
	encoder := unaBladeMp3Enc.create(encoderModule);
      end;
      2: begin
	infoMessage('* Using Lame encoder');
	encoder := unaLameMp3Enc.create(encoderModule);
      end
      else
	encoder := nil;
    end;
    //
    if ((nil <> encoder) and (BE_ERR_SUCCESSFUL = encoder.errorCode)) then begin
      // configure encoder
      minBR := config.get('stream.bitrate', unsigned(128));
	infoMessage(' - Stream bitrate: ' + int2str(minBR));
      maxBR := config.get('stream.maxBitrate', unsigned(192));
	infoMessage(' - Stream maximum bitrate: ' + int2str(maxBR));
      samplesRate := config.get('target.pcm.sps', unsigned(44100));
	infoMessage(' - Sampling rate: ' + int2str(samplesRate));
      stereoMode := choice(1 = config.get('target.pcm.stereo', unsigned(1)), unsigned(BE_MP3_MODE_STEREO), BE_MP3_MODE_MONO);
	infoMessage(' - Stereo mode: ' + choice(BE_MP3_MODE_STEREO = stereoMode, 'STEREO', 'MONO'));
      //
      mp3Config := nil;
      case (encoderModel) of

	//
	1: begin	// Blade
	  fillChar(bladeConfig, sizeOf(bladeConfig), #0);
	  bladeConfig.dwConfig := BE_CONFIG_MP3;
	  with bladeConfig.r_mp3 do begin
	    dwSampleRate := samplesRate;
	    byMode := stereoMode;
	    wBitrate := minBR;
	    // change as you need
	    bPrivate := false;
	    bCRC :=  false;
	    bCopyright :=  false;
	    bOriginal :=  false;
	  end;
	  mp3Config := @bladeConfig;
	end;

	//
	2: begin	// Lame
	  fillChar(lameConfig, sizeOf(lameConfig), #0);
	  lameConfig.dwConfig := BE_CONFIG_LAME;
	  with lameConfig.r_lhv1 do begin
	    dwStructVersion := CURRENT_STRUCT_VERSION;
	    dwStructSize := sizeOf(lameConfig);
	    dwSampleRate := samplesRate;
	    //dwReSampleRate := 0;
	    nMode := stereoMode;
	    dwBitrate := minBR;
	    dwMaxBitrate := maxBR;
	    nPreset := LQP_NOPRESET;
	    dwMpegVersion := MPEG2;
	    //dwPsyModel := 0;
	    //dwEmphasis := 0;
	    // change as you need
	    bPrivate := false;
	    bCRC :=  false;
	    bCopyright := false;
	    bOriginal := false;
	    //
	    bWriteVBRHeader := config.get('stream.vbr.header.write', false);
	      infoMessage(' - Write VBR header: ' + bool2strStr(bWriteVBRHeader));
	    bEnableVBR := config.get('stream.vbr.enabled', false);
	      infoMessage(' - VBR enabled: ' + bool2strStr(bEnableVBR));
	    nVBRQuality := config.get('stream.vbr.quality', unsigned(0));
	      infoMessage(' - VBR quality: ' + int2str(nVBRQuality));
	    //
	    if (bEnableVBR) then
	      // chaneg as required
	      nVbrMethod := VBR_METHOD_NEW
	    else
	      nVbrMethod := VBR_METHOD_NONE;
	    //
	    bNoRes := true;
	    bStrictIso := false;
	  end;
	  mp3Config := @lameConfig;
	end;
      end;

      //
      if (nil <> mp3Config) then begin
	result := false;
	//
	if (BE_ERR_SUCCESSFUL = encoder.setConfig(mp3Config)) then begin
	  if (BE_ERR_SUCCESSFUL = encoder.open()) then begin
	    infoMessage('* Encoder has been initializated successfully.');
	    result := true;
	  end
	  else
	    infoMessage('* Encoder cannot be opened, error code: 0x' + int2str(encoder.errorCode, 16));
	end
	else
	  infoMessage('* Encoder config fails, error code: 0x' + int2str(encoder.errorCode, 16));
      end;
    end
    else begin
      if (nil = encoder) then
	infoMessage('* No encoder model specified, terminating..')
      else
	infoMessage('* Encoder model #' + int2str(encoderModel) + ' cannot be found.'#13#10'  Please check if required encoder DLL is present on your system.');
      //
      result := false;
    end;
  end;

  //
  if (not result) then
    done();

  //
  freeAndNil(config);
end;

var
  finalFlush: bool = false;

// --  --
function flush(): bool;
var
  size: unsigned;
begin
  if (finalFlush or (sizeOf(feedBuffer) < encoder.availableOutputDataSize)) then begin
    //
    size := encoder.read(@feedBuffer, sizeOf(feedBuffer));
    result := (0 < size);
    if (result) then
      writeToFile(mp3File, @feedBuffer, size);
  end
  else begin
    result := false;
    Sleep(10);
    //
  end;
end;

var
  saneBufSize: unsigned = $100000;	// do not feed the encoder over this size

const
  saneBufSizeDelta = $10000;		// increase delta for saneBufSize

// --  --
function feed(): bool;
var
  size: unsigned;
begin
  result := true;
  //
  if (saneBufSize < encoder.availableLazyDataSize) then begin
    // give encoder a chance to make the conversion
    result := false;
    Sleep(50);
    //
    if (encoder.inputChunkSize > encoder.availableLazyDataSize) then
      // we were sleeping too long - increase the sane buffer size
      inc(saneBufSize, saneBufSizeDelta);
  end;
  //
  size := waveResampler.read(@feedBuffer, sizeOf(feedBuffer));
  if (0 < size) then
    encoder.lazyWrite(@feedBuffer, size)
  else begin
    // we are reading too fast, let sleep a while
    result := false;
    Sleep(10);
  end;
  //
  result := flush() and result;
end;

// --  --
procedure run();
var
  mark: int64;
  h, m, s, ms: unsigned;
begin
  infoMessage('* Starting conversion..'#13#10);

  // 1. open devices
  waveResampler.open();
  waveReader.open();
  //
  mark := timeMark();

  // 2. read the source wav, feeding the encoder
  encoder.priority := THREAD_PRIORITY_ABOVE_NORMAL;
  while (not waveReader.streamIsDone) do begin
    //
    if (feed()) then
      write(' [ ] Reading input file: ' + int2str(percent(waveReader.streamPosition, waveReader.streamSize)) + '% done ..   '#13);
  end;
  infoMessage(' [x] Reading input file: done.                    '#13);
  waveReader.close();	// free reader resources

  // 3. feed the encoder with resampled data
  waveResampler.priority := THREAD_PRIORITY_ABOVE_NORMAL;
  while ((waveResampler.chunkSize < waveResampler.getDataAvailable(true)) or (0 < waveResampler.getDataAvailable(false))) do begin
    //
    if (feed()) then begin
      //
      write(' [ ] Feeding the encoder: ' + int2str(waveResampler.getDataAvailable(false), 10, 3) + ' bytes left ..     '#13);
      //
      if (waveResampler.isOpen() and (1 > waveResampler.getDataAvailable(true))) then begin
	//
	encoder.priority := THREAD_PRIORITY_HIGHEST;	// boost encoder
	waveResampler.close();	// do not need to waste CPU cycles on empty resample thread
      end;
    end
    else
      write(' [ ] Feeding the encoder: idle ..                                    '#13);
    //
  end;
  //
  waveResampler.close();	// free resampler resources
  infoMessage(' [x] Feeding the encoder: done.                      '#13);

  // 4. wait for encoder to finish
  encoder.priority := THREAD_PRIORITY_HIGHEST;
  while (encoder.inputChunkSize < encoder.availableLazyDataSize) do begin
    //
    write(' [ ] Waiting for encoder to complete: ' + int2str(encoder.availableLazyDataSize, 10, 3) + ' bytes left..      '#13);
    Sleep(300);
  end;
  encoder.close();	// will flush the rest of not-encoded yet stream
  infoMessage(' [x] Waiting for encoder to complete: done.                   '#13);

  // 5. flush the rest of stream into destination file
  finalFlush := true;
  while (0 < encoder.availableOutputDataSize) do begin
    //
    if (flush()) then
      write(' [ ] Flushing the output file: ' + int2str(encoder.availableOutputDataSize, 10, 3) + ' bytes left ..   '#13);
    //
    Sleep(50);
  end;
  infoMessage(' [x] Flushing the output file: done.                       '#13);

  // calculate the time used
  mark := timeElapsed64(mark);
  h := mark div (3600000);
  m := mark div (60000) - h * 60;
  s := mark div (1000) - m * 60 - h * 60 * 60;
  ms := mark mod (1000);
  infoMessage(#13#10#13#10'* Conversion is done, ' + adjust(int2str(h), 2, '0') + ':' + adjust(int2str(m), 2, '0') + ':' + adjust(int2str(s), 2, '0') + '.' + adjust(int2str(ms), 3, '0') + ' elapsed.');
end;


// -- main --

begin
  infoMessage('wav2mp3,  version 1.0  Copyright (c) 2002-2005 Lake of Soft, Ltd');
  infoMessage('VC components version 2.5 Pro           http://lakeofsoft.com/vc'#13#10);
  //
  if (paramCount < 1) then begin
    infoMessage('  syntax: wav2mp3 [wav_file [mp3_file]]'#13#10#13#10 +
		'Check the wav2mp3.ini file for encoder options.');
  end
  else begin
    if (init()) then
      try
	run();
      finally
	done();
      end;
  end;
end.

⌨️ 快捷键说明

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