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

📄 unamsacmclasses.pas

📁 Voice Commnucation Components for Delphi
💻 PAS
📖 第 1 页 / 共 5 页
字号:
    f_drvGlobalSrc: HGLOBAL;
    f_drvGlobalDst: HGLOBAL;
{$ENDIF}
    f_codec: unaMsAcmCodec;
  protected
    {DP:METHOD
      Used to return different statuses of header.
    }
    function getStatus(index: int): bool; override;
    {DP:METHOD
      Used to set different statuses of header.
    }
    procedure setStatus(index: int; value: bool); override;
    function isDoneHeader(): bool; override;
    function isInQueue(): bool; override;
    procedure rePrepare(); override;
  public
    {DP:METHOD
      Creates ACM codec header and allocates required buffers.
    }
    constructor create(codec: unaMsAcmCodec; srcSize: unsigned; dstSize: unsigned);
    destructor Destroy(); override;
    //
    {DP:METHOD
      Writes data to the source codec buffer.
    }
    procedure write(data: pointer; size: unsigned; offset: unsigned = 0);
    //
    {DP:METHOD
      Returns true if header is released by codec.
    }
    property isDone: bool index ACMSTREAMHEADER_STATUSF_DONE read getStatus write setStatus;
    {DP:METHOD
      Returns true if header is still in codec queue.
    }
    property inQueue: bool index ACMSTREAMHEADER_STATUSF_INQUEUE read getStatus write setStatus;
    {DP:METHOD
      Returns true if header was prepared.
    }
    property isPrepared: bool index ACMSTREAMHEADER_STATUSF_PREPARED read getStatus write setStatus;
  end;


  // --  --
  unaAcmCodecDriverMode = (unacdm_acm, unacdm_installable, unacdm_internal, unacdm_openH323plugin);


  //
  // -- unaMsAcmCodec --
  //

  {DP:CLASS
    This class is wrapper over Windows Multimedia streams API. Create it specifying the driver you wish to use with the stream.
    You can get list of available drivers from unaMsAcm class instance.

    <P />Codec usually takes source (input) stream, converts it into another wave format, and produces destination (output) stream.
    Before opening the codec you should specify source and destination formats using the setFormat() method.
    isSrc parameter is true for source format and false for destination. tag and index are specific for selected driver.

    <P />For example, Microsoft PCM Converter driver has tag = 1 and index specifies sampling parameters.
    So, if you specify tag=1, index=1 as source and tag=1, index=9 as destination, codec will convert 8,000 kHz; 8 Bit; stereo PCM stream into 22,050 kHz; 8 Bit; stereo PCM stream.
    You can easily enumerate all formats supported by specific driver using the unaMsAcmDriver.enumFormats() method.

    <P />After setting source and destination formats call the open() method to activate the codec.
    If you wish to check specified formats conversion is supported by codec, rather than opening it, specify true for query parameter.
    open() returns MMSYSERR_NOERR if codec was activated successfully. After that you need to feed the source stream using write() method, and periodically check destination stream, calling read() method.
    When you are finished with codec, destroy it or call the close() method.
  }
  unaMsAcmCodec = class(unaMsAcmStreamDevice)
  private
    f_driver: unaMsAcmDriver;
    f_driverLibrary: wideString;
    f_driverMode: unaAcmCodecDriverMode;
    //
    f_oH323codec: una_openH323plugin;
    f_oH323codecOldIndex: int;
    //
    f_async: bool;
    f_highPriority: bool;
    f_streamInstance: ACMDRVSTREAMINSTANCE;	// used by installable drivers
    //
    f_filterFormat: pWAVEFILTER;
    //
    function reset(timeout: unsigned): MMRESULT;
    function getChunkSize(inSize: unsigned; out outSize: unsigned; flags: DWORD = ACM_STREAMSIZEF_SOURCE): MMRESULT;
    function streamConvert(header: unaMsAcmCodecHeader; flags: DWORD): MMRESULT;
    procedure setDriverLibrary(const value: wideString);
    function getoH323pluginDesc(index: int): ppluginCodec_definition;
  protected
    function execute(globalIndex: unsigned): int; override;
    //
    function doOpen(flags: unsigned): MMRESULT; override;
    function doClose(timeout: unsigned = 1): MMRESULT; override;
    function open2(query: bool = false; timeout: unsigned = 10000; flags: unsigned = 0): MMRESULT; override;
    //
    function prepareHeader(header: unaMsAcmDeviceHeader): MMRESULT; override;
    function unprepareHeader(header: unaMsAcmDeviceHeader): MMRESULT; override;
    {DP:METHOD
      Returns true.
    }
    function getMasterIsSrc2(): bool; override;
  public
    {DP:METHOD
      Creates ACM codec class instance.
    }
    constructor create(driver: unaMsAcmDriver; realtime: bool = false; overNum: unsigned = 0; highPriority: bool = false; driverMode: unaAcmCodecDriverMode = unacdm_acm);
    //
    procedure BeforeDestruction(); override;
    //
    {DP:METHOD
      Sets the source or destination format for codec.
    }
    procedure setFormatIndex(isSrc: bool; tag, index: unsigned);
    {DP:METHOD
      Use this method when you do not know the exact format supported by the codec, but do know the driver, tag and index of the desired format.
    }
    procedure setFormatSuggest(isSrc: bool; desiredDriver: unaMsAcmDriver; tag, index: unsigned; flags: unsigned = ACM_FORMATSUGGESTF_NCHANNELS + ACM_FORMATSUGGESTF_NSAMPLESPERSEC + ACM_FORMATSUGGESTF_WBITSPERSAMPLE); overload;
    {DP:METHOD
      Use this method when you do know non-PCM parameters of source or dest stream.
    }
    function setFormatSuggest(isSrcPCM: bool; const format: WAVEFORMATEX): bool; overload;
    {DP:METHOD
      Use this method when you do know PCM parameters of source or dest stream.
    }
    function setPcmFormatSuggest(isSrcPCM: bool; samplesPerSec: unsigned = c_defSamplingSamplesPerSec; bitsPerSample: unsigned = c_defSamplingBitsPerSample; numChannels: unsigned = c_defSamplingNumChannels; formatTag: unsigned = 0): bool; overload;
    {DP:METHOD
      Use this method when you do know PCM parameters of source or dest stream.
    }
    function setPcmFormatSuggest(isSrcPCM: bool; const pcmFormat: WAVEFORMATEX; formatTag: unsigned): bool; overload;
    {DP:METHOD
      Returns the driver used to perform the codec job.
    }
    property driver: unaMsAcmDriver read f_driver write f_driver;
    {DP:METHOD
      Specifies library file (DLL) for a driver. Not used with ACM codecs, where you should specify driver directly instead.
    }
    property driverLibrary: wideString read f_driverLibrary write setDriverLibrary;
    {DP:METHOD
      Since codec is input/output device, we need to have second chunk of data.
    }
    property dstChunkSize;
    {DP:METHOD
      Specifies driver mode: ACM, installable or internal.
    }
    property driverMode: unaAcmCodecDriverMode read f_driverMode write f_driverMode;
    {}
    property oH323codecDesc[index: int]: ppluginCodec_definition read getoH323pluginDesc;
  end;


  //
  // -- unaWaveHeader --
  //

  {DP:CLASS
    This class stores the wave data which will be send or received to/from Windows wave device.
  }
  unaWaveHeader = class(unaMsAcmDeviceHeader)
  private
    f_header: WAVEHDR;
  protected
    procedure rePrepare(); override;
    //
    function getStatus(index: int): bool; override;
    procedure setStatus(index: int; value: bool); override;
    function isDoneHeader(): bool; override;
    function isInQueue(): bool; override;
  public
    {DP:METHOD
      Creates wave buffer header and allocates required buffers.
    }
    constructor create(device: unaWaveDevice; size: unsigned; data: pointer = nil);
    destructor Destroy(); override;
    //
    function setData(data: pointer; size: unsigned; offset: int = 0): int;
    //
    {DP:METHOD
      Returns true if header is released by device.
    }
    property isDone: bool index WHDR_DONE read getStatus write setStatus;
    {DP:METHOD
      Returns true if header is still in device queue.
    }
    property inQueue: bool index WHDR_INQUEUE read getStatus write setStatus;
    {DP:METHOD
      Returns true if header was prepared.
    }
    property isPrepared: bool index WHDR_PREPARED read getStatus write setStatus;
    {DP:METHOD
      Returns true if header is the beginning of the loop.
    }
    property isBeginLoop: bool index WHDR_BEGINLOOP read getStatus write setStatus;
    {DP:METHOD
      Returns true if header is the end of the loop.
    }
    property isEndLoop: bool index WHDR_ENDLOOP read getStatus write setStatus;
  end;

  //
  // -- unaWaveDevice --
  //

  {DP:CLASS
    This abstract class is used as base for unaWaveInDevice (recorder) and unaWaveOutDevice (playback) devices.

    <P />Since both In and Out devices are working with PCM streams only, we can simplify the process of specifying wave formats.
    Instead of tag/index pair setSampling() method takes three parameters: samples per second, bits per sample and number of channels.
    Commonly used values for samples per second are 8,000; 11,025; 22,050 and 44,100. Bits per sample could be 8 or 16 or more.
    Number of channels is usually 1 (mono) or 2 (stereo).
  }
  unaWaveDevice = class(unaMsAcmStreamDevice)
  private
    f_deviceID: unsigned;
    f_mapped: bool;
    f_direct: bool;
    //
{$IFDEF DEBUG_LOG }
    function displayHeadersUsage(): bool;
{$ENDIF}
  protected
    function addHeader(header: unaWaveHeader): MMRESULT; virtual; abstract;
    function onHeaderDone(header: unaWaveHeader; wakeUpByHeaderDone: bool): bool; virtual;
    //
    function execute(globalIndex: unsigned): int; override;
    //
    function open2(query: bool = false; timeout: unsigned = 10000; flags: unsigned = 0): MMRESULT; override;
  public
    {DP:METHOD
      From Microsoft MSDN:
      <BR />mapped - The deviceID parameter specifies a waveform-audio device to be mapped to by the wave mapper.
      <BR />direct - If this flag is specified, the ACM driver does not perform conversions on the audio data.
    }
    constructor create(deviceID: unsigned = WAVE_MAPPER; mapped: bool = false; direct: bool = false; isIn: bool = true; overNum: unsigned = 0);
    {DP:METHOD
      Since most wave devices supports PCM formats only it is handy to have this method.
    }
    function setSampling(samplesPerSec: unsigned = c_defSamplingSamplesPerSec; bitsPerSample: unsigned = c_defSamplingBitsPerSample; numChannels: unsigned = c_defSamplingNumChannels): bool; overload;
    function setSampling(const pcmFormat: WAVEFORMATEX): bool; overload;
    function setSampling(const pcmFormat: unaPCMFormat): bool; overload;
    //
    {DP:METHOD
      From Microsoft MSDN:
      <BR />direct - If this flag is specified, the ACM driver does not perform conversions on the audio data.
    }
    property direct: bool read f_direct write f_direct;
    {DP:METHOD
      From Microsoft MSDN:
      <BR />mapped - The deviceID parameter specifies a waveform-audio device to be mapped to by the wave mapper.
    }
    property mapped: bool read f_mapped write f_mapped;
    {DP:METHOD
      Device Id.
    }
    property deviceId: unsigned read f_deviceId write f_deviceId;
  end;


  //
  // -- unaWaveInDevice --
  //
  {DP:CLASS
    Use this class to record live audio.
    deviceID parameter used to construct instances of this class can be
    from 0 to unaWaveInDevice.getDeviceCount() - 1, or you can use WAVE_MAPPER value instead.

    <P />After opening the device check periodically output stream by calling read() method,
    or use onDataAvailable() event to receive new data chunks.
  }
  unaWaveInDevice = class(unaWaveDevice)
  private
    f_caps: WAVEINCAPSW;
    //
    function feedHeader(header: unawaveHeader = nil): bool;
  protected
    procedure startIn(); override;
    procedure startOut(); override;
    //
    function doOpen(flags: unsigned): MMRESULT; override;
    function doClose(timeout: unsigned = 1): MMRESULT; override;
    function doGetErrorText(errorCode: MMRESULT): string; override;
    function doGetPosition(): int64; override;
    //
    function afterOpen(): MMRESULT; override;
    //
    function prepareHeader(header: unaMsAcmDeviceHeader): MMRESULT; override;
    function unprepareHeader(header: unaMsAcmDeviceHeader): MMRESULT; override;
    function addHeader(header: unaWaveHeader): MMRESULT; override;
    //
    function onHeaderDone(header: unaWaveHeader; wakeUpByHeaderDone: bool): bool; override;
    {DP:METHOD
      Displays a format choose dialog. Reallocates (if necessary) given format.
    }
    function formatChooseDef2(var format: pWAVEFORMATEX): MMRESULT; override;
    {DP:METHOD
      Returns false.
    }
    function getMasterIsSrc2(): bool; override;
  public
    constructor create(deviceID: unsigned = WAVE_MAPPER; mapped: bool = false; direct: bool = false; overNum: unsigned = 0);
    procedure AfterConstruction(); override;
    procedure BeforeDestruction(); override;
    //
    function getCaps(): pWAVEINCAPSW; overload;
    function formatChoose(var format: pWAVEFORMATEX; const title: string = ''; style: unsigned = ACMFORMATCHOOSE_STYLEF_INITTOWFXSTRUCT; enumFlag: unsigned = ACM_FORMATENUMF_HARDWARE + ACM_FORMATENUMF_INPUT; enumFormat: pWAVEFORMATEX = nil): MMRESULT;
    // -- class functions --
    class function getCaps(deviceID: unsigned; var caps: WAVEINCAPSW): bool; overload;
    class function getDeviceCount(): unsigned;
    class function getErrorText(errorCode: MMRESULT): string;
  end;


  //
  // -- unaWaveOutDevice --
  //
  {DP:CLASS
    Use this class to playback PCM audio stream.
    deviceID parameter used to construct instance of this class can be
    from 0 to unaWaveOutDevice.getDeviceCount() - 1, or you can use WAVE_MAPPER value instead.

    <P />After opening the device feed periodically input stream by calling write() method.
    If device is unable to load next chunk when needed it can produce a chunk of "silence" and feed it automatically to hardware.
    Use autoFeed property to enable/disable this behavior.
  }
  unaWaveOutDevice = class(unaWaveDevice)
  private
    f_caps: WAVEOUTCAPSW;
    f_outOfStream: int64;
    f_outOfData: int64;
//    f_sanity: int64;
    //
    f_onACF: unaWaveDataEvent;
    f_onACD: unaWaveDataEvent;
    //
    function getPitch(): unsigned;
    function getPlaybackRate(): unsigned;
    function getDeviceVolume(): unsigned;
    procedure setPitch(value: unsigned);
    procedure setPlaybackRate(value: unsigned);
    procedure setDeviceVolume(value: unsigned);
  protected
    procedure startIn(); override;
    procedure startOut(); override;
    //
    function doOpen(flags: unsigned): MMRESULT; override;
    function doClose(timeout: unsigned = 1): MMRESULT; override;
    function doGetErrorText(errorCode: MMRESULT): string; override;
    function doGetPosition(): int64; override;

⌨️ 快捷键说明

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