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

📄 amixer.pas

📁 语音与识别技术包含很多C语言处理模块系统
💻 PAS
📖 第 1 页 / 共 3 页
字号:
unit AMixer;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
  MMSystem;

(*
 * TAudioMixer v1.4 (FREEWARE component)
 * ----------------
 * Released 2 Jul 2000
 *
 * This component can cache data from audio mixer. It has direct support for
 * getting/setting volume of any control (It can set also set state of that
 * "Selected" CheckBox in standard Windows Volume Control program). You can
 * better use other features of mixer, but that's more difficult than volume
 * setting and you must know something about audio mixer.
 *
 * The mixer has following structure (as it is in this component) :
 *
 * Destinations (destinations should be for example: Playback, Recording and Voice commands)
 *   |
 *   |--Destination[0]        (if you want to get volume of this call GeVolume (<ThisDestinationNum>,-1,...))
 *   |    |                                                                          (=0)           ----
 *   |    |--Data:TMixerLine
 *   |    |--Controls         (controls of the line, ex: Master volume, master mute)
 *   |    |    |
 *   |    |    |--Control[0]
 *   |    |    |--Control[1]
 *   |    |    |--Control[..]
 *   |    |
 *   |    |--Connections      (ex: Wave, MIDI, CD Audio, Line-In,...)
 *   |         |
 *   |         |--Connection[0]   (GetVolume (<ThisDestinationNum>,<ThisConnectionNumb>,...))
 *   |         |    |                               (=0)                 (=0)
 *   |         |    |--Data:TMixerLine
 *   |         |    |--Controls   (here can be volume and mute)
 *   |         |         |
 *   |         |         |--Control[0]
 *   |         |         |--Control[1]
 *   |         |         |--Control[..]
 *   |         |
 *   |         |--Connection[1]
 *   |         |--Connection[..]
 *   |
 *   |--Destination[1]
 *   |--Destination[..]
 *
 *
 * There are many types of controls - checkbox, list, slider,... they are
 * described in Windows help. Common ones are volume slider, mute checkbox or
 * volume meter.
 *
 * This component is universal, so you can work with all controls through it,
 * but this is difficult. You can simply get/set volume level by procedures
 * GetVolume or SetVolume (description is near their declaration; use - see
 * example program).
 *
 *
 * What's New
 * ----------
 * 1.4  (2 Jun 2000)
 *      - added some examples
 *      - great improvements by Fabrice Fouqet :
 *          - added properties FDriverVersion, FManufacturer, FProductId,
 *            FNumberOfLine and FProductName
 *          - added functions GetMute/SetMute and GetPeak
 *          - changed function GetVolume (also returns if selected control
 *            is stereo or mono)
 * 1.16 (20 May 1999)
 *      - made compatible with Delphi 2.0 (this was done by Tom Lisjac)
 * 1.15 (17 May 1999)
 *      - corrected "Windows couldn't be shut down while TAudioMixer is being used" problem
 *            (many thanks to Jean Carlo Solis Ubago, who fixed this)
 *      - added example showing how to set bass / treble
 * 1.12 (24 Mar 1999)
 *      - corrected setting "selected" state
 * 1.11 (4 Jan 1999)
 *      - now it supports also MIXERCONTROL_CONTROLTYPE_MUX flag
 *        (I got SB Live! for Christmas (:-)) and my component didn't work
 *         properly, this corrects that problem)
 * 1.1  (16 Nov 1998)
 *      - made compatible with Delphi 4
 *      - corrected memory leaks (by Ishida Wataru)
 *      - some another minor changes (by Ishida Wataru)
 *      - added another example
 *      - added AMixer.dcr
 * 1.0  (18 Aug 1998)
 *      - initial version
 *
 *
 * You can use this component freely in your programs. But if you do so, please
 * send me an e-mail. I would like to know if it is useful.
 *
 * (C) Vit Kovalcik
 *
 * e-mail: vkovalcik@iname.com
 * WWW: http://www.fi.muni.cz/~xkovalc
 * (if it will not work try http://www.geocities.com/SiliconValley/Hills/1335)
 *)

{Note:
  When no mixer is present TAudioMixer.Destinations will be nil.
  If you then check Destinations.Count it will raise exception,
  so be sure to check TAudioMixer.MixerCount first.}

type
  TAudioMixer=class;

  TPListFreeItemNotify=procedure (Pntr:Pointer) of object;
  TMixerChange=procedure (Sender:TObject;MixerH:HMixer;ID:Integer) of object;
    {MixerH is handle of mixer, which sent this message.
     ID is ID of changed item (line or control).}

  TPointerList=class(TObject)
  private
    FOnFreeItem:TPListFreeItemNotify;
    Items:Tlist;
  protected
    function GetPointer (Ind:Integer):Pointer;
    function GetCount :integer;
  public
    constructor Create;
    destructor Destroy; override;
    procedure Clear;
    procedure Add (Pntr:Pointer);
    property Count:Integer read GetCount;
    property Pointer[Ind:Integer]:Pointer read GetPointer; default;
    property OnFreeItem:TPListFreeItemNotify read FOnFreeItem write FOnFreeItem;
  end;

  TMixerControls=class(TObject)
  private
    heap:pointer;
    FControls:TPointerList;
  protected
    function GetControl (Ind:Integer):PMixerControl;
    function GetCount:Integer;
  public
    constructor Create (AMixer:TAudioMixer; AData:TMixerLine);
    destructor Destroy; override;
    property Control[Ind:Integer]:PMixerControl read GetControl; default;
    property Count:Integer read GetCount;
  end;

  TMixerConnection=class(TObject)
  private
    XMixer:TAudioMixer;
    FData:TMixerLine;
    FControls:TMixerControls;
  public
    constructor Create (AMixer:TAudioMixer; AData:TMixerLine);
    destructor Destroy; override;
    property Controls:TMixerControls read FControls;
    property Data:TMixerLine read FData;
  end;

  TMixerConnections=class(TObject)
  private
    XMixer:TAudioMixer;
    FConnections:TPointerList;
  protected
    procedure DoFreeItem (Pntr:Pointer);
    function GetConnection (Ind:Integer):TMixerConnection;
    function GetCount:Integer;
  public
    constructor Create (AMixer:TAudioMixer; AData:TMixerLine);
    destructor Destroy; override;
    property Connection[Ind:Integer]:TMixerConnection read GetConnection; default;
    property Count:Integer read GetCount;
  end;

  TMixerDestination=class(TObject)
  private
    XMixer:TAudioMixer;
    FData:TMixerLine;
    FControls:TMixerControls;
    FConnections:TMixerConnections;
  public
    constructor Create (AMixer:TAudioMixer; AData:TMixerLine);
    destructor Destroy; override;
    property Connections:TMixerConnections read FConnections;
    property Controls:TMixerControls read FControls;
    property Data:TMixerLine read FData;
  end;

  TMixerDestinations=class(TObject)
  private
    FDestinations:TPointerList;
  protected
    function GetDestination (Ind:Integer):TMixerDestination;
    procedure DoFreeItem (Pntr:Pointer);
    function GetCount:Integer;
  public
    constructor Create (AMixer:TAudioMixer);
    destructor Destroy; override;
    property Count:Integer read GetCount;
    property Destination[Ind:Integer]:TMixerDestination read GetDestination; default;
  end;

  TAudioMixer = class(TComponent)
  private
    XWndHandle:HWnd;

    FDestinations:TMixerDestinations;
    FMixersCount:Integer;
    FMixerHandle:HMixer;
    FMixerId:Integer;
    FMixerCaps:TMixerCaps;
    FDriverVersion: MMVERSION;
    FManufacturer: String;
    FProductId: Word;
    FNumberOfLine: Integer;
    FProductName: String;
    FOnLineChange:TMixerChange;
    FOnControlChange:TMixerChange;
  protected
    procedure SetMixerId (Value:Integer);
    procedure MixerCallBack (var Msg:TMessage);
    procedure CloseMixer;
  published
    constructor Create (AOwner:TComponent); override;
    destructor Destroy; override;
    property DriverVersion: MMVERSION read FDriverVersion;
    property ProductId: WORD read FProductId;
    property NumberOfLine: Integer read FNumberOfLine;
    property Manufacturer: string read FManufacturer;
    property ProductName: string read FProductName;
    property MixerId:Integer read FMixerId write SetMixerId;
      {Opened mixer - value must be in range 0..MixersCount-1
       If no mixer is opened this value is  -1}
    property OnLineChange:TMixerChange read FOnLineChange write FOnLineChange;
    property OnControlChange:TMixerChange read FOnControlChange write FOnControlChange;
  public
    function GetVolume (ADestination, AConnection:Integer; var LeftVol, RightVol, Mute:Integer; var Stereo, VolDisabled, MuteDisabled:Boolean):Boolean;
      {This function return volume of selected Destination and Connection.
       ADestination must be from range 0..Destinations.Count-1
       AConnection must be in range 0..Destinations[ADestination].Connections.Count-1
       If you want to read master volume of some Destination, you have to
         set AConnection to -1.
       If LeftVol, RightVol or Mute is not supported by queried connection,
         it's return value will be -1.

       LeftVol and RightVol are in range 0..65536

       If Mute is non-zero then the connection is silent.
       If specified line is recording source then Mute specifies if programs will
         record from this connection (it is copy of "Select" Checkbox in
         standard Windows Volume Control program)
       Stereo is true, then this control is stereo.
       VolDisabled or MuteDisabled is True when you cannot apply settings to this
         control (but can read it).

       Return value of the function is True if no error has occured,
         otherwise it returns False.}
    function SetVolume (ADestination, AConnection:Integer; LeftVol, RightVol, Mute:Integer):Boolean;
      {This function sets volume.
       If you set RightVol to -1 and connection is stereo then LeftVol will be
       copied to RightVol.
       If LeftVol or Mute is -1 then this value will not be set.

       Return value is True if ADestination and AConnection are correct, otherwise False.}

    function GetPeak(ADestination, AConnection:Integer; var LeftPeak, RightPeak:Integer):Boolean;
    function GetMute(ADestination, AConnection:Integer; var Mute:Boolean):Boolean;
    function SetMute(ADestination, AConnection:Integer; Mute:Boolean):Boolean;

    property Destinations:TMixerDestinations read FDestinations;
      {Ind must be in range 0..DestinationsCount-1}
    property MixerCaps:TMixerCaps read FMixerCaps;
    property MixerCount:Integer read FMixersCount;
      {Number of mixers present in system; mostly 1}
    property MixerHandle:HMixer read FMixerHandle;
      {Handle of opened mixer}
  end;

procedure Register;

implementation

{------------}
{TPointerList}
{------------}

constructor TPointerList.Create;
begin
  Items := TList.Create;
end;

destructor TPointerList.Destroy;
begin
  Clear;
  Items.Free;
end;

procedure TPointerList.Add (Pntr:Pointer);
begin
  Items.Add (Pntr);
end;

function TPointerList.GetPointer (Ind:Integer):Pointer;
begin
  Result := Items[Ind];
end;

procedure TPointerList.Clear;
var I:Integer;
begin
  for I := 0 to Items.Count-1 do begin
    If Assigned (FOnFreeItem) then
      FOnFreeItem (Items[I])
  end;
  Items.Clear;
end;

function TPointerList.GetCount:Integer;
begin
  Result := Items.Count;
end;

{--------------}
{TMixerControls}
{--------------}

constructor TMixerControls.Create (AMixer:TAudioMixer; AData:TMixerLine);
var MLC:TMixerLineControls;
    A,B:Integer;
    P:PMixerControl;
begin
  FControls := TPointerList.Create;
  GetMem (P, SizeOf(TMixerControl)*AData.cControls);
  heap := P;
  MLC.cbStruct := SizeOf(MLC);
  MLC.dwLineID := AData.dwLineID;
  MLC.cbmxctrl := SizeOf(TMixerControl);
  MLC.cControls := AData.cControls;
  MLC.pamxctrl := P;
  A := MixerGetLineControls(AMixer.MixerHandle, @MLC, MIXER_GETLINECONTROLSF_ALL);
  If A = MMSYSERR_NOERROR then
  begin
    For B := 0 to AData.cControls-1 do
    begin
      FControls.Add (P);
      P := PMixerControl (DWORD(P) + sizeof (TMixerControl));
    end;
  end;
end;

destructor TMixerControls.Destroy;
begin
  FControls.free;
  freemem(heap);
  inherited;
end;

function TMixerControls.GetControl (Ind:Integer):PMixerControl;
begin
  Result := FControls.Pointer[Ind];
end;

function TMixerControls.GetCount:Integer;
begin
  Result := FControls.Count;
end;

{----------------}
{TMixerConnection}
{----------------}

constructor TMixerConnection.Create (AMixer:TAudioMixer; AData:TMixerLine);
begin

⌨️ 快捷键说明

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