如何改变系统的音量大小,(象windows的音量调节程序一样),API函数调用,详细见内:(100分)

  • 主题发起人 主题发起人 魏启明
  • 开始时间 开始时间

魏启明

Unregistered / Unconfirmed
GUEST, unregistred user!
要改变系统的音量输出的大小,
象windows的音量控制程序sndvol32.exe一样;(1)
而不是象Windows Media Player的音量调节那样;(2)

//回答问题的同志请注意这二者之间的差别。
我不知道者之间的差别,大概前者控制的是底层的东西,而后者控制的则是表象
我不知道原理只能瞎猜。

搜索类似的贴子,发现只能实现第二种功能,所有的回答都不超过下面这个贴子的范围;
所以不要再提供相似的回答了。
//*******************************************************************//
来自:程云, 时间:2000-6-8 17:06:00, ID:262698
控制音量要用到waveOutSetVlume函数,此函数的声明在MMSystem.h单元中。
此单放在Delphi目录下的Source/rtl/win中

主意这儿用到两个函数waveOutSetVlume和waveOutGetVolume,不要用混,
我第一次用它们时就给搞混了,好费事。

程序如下:

三个TrackBar的属性设置:Max:=255;Frequency:=16;

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
ComCtrls, mmsystem;

type
TForm1 = class(TForm)
TrackBar1: TTrackBar;
TrackBar2: TTrackBar;
TrackBar3: TTrackBar;
procedure TrackBar1Change(Sender: TObject);
procedure TrackBar2Change(Sender: TObject);
procedure TrackBar3Change(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;


var
Form1: TForm1;

implementation

{$R *.DFM}

//音量控制
procedure TForm1.TrackBar1Change(Sender: TObject);
var
t,v:Longint;
begin

// if a=0 then
Exit;
t:=TrackBar1.Position;
v:=(t shl 8)or(t shl 24);
waveOutSetVolume(0,v);
end;


//左声道控制
procedure TForm1.TrackBar2Change(Sender: TObject);
var
t,v:Longint;
begin

t:=TrackBar2.Position;
waveOutGetVolume(0,@v);
v:=v and $ffff0000 or (t shl 8);
waveOutSetVolume(0,v);
end;


//右声道控制
procedure TForm1.TrackBar3Change(Sender: TObject);
var
t,v:Longint;
begin

t:=TrackBar3.Position;
waveOutGetVolume(0,@v);
v:=v and $0000ffff or (t shl 24);
waveOutSetVolume(0,v);
end;


//获得当前音量值
procedure TForm1.FormCreate(Sender: TObject);
var
v:longint;
begin

waveOutGetVolume(0,@v);
TrackBar2.Position:=hi(v);
TrackBar3.Position:=hi(v shr 16);
if hi(v)>hi(v shr 16) then

TrackBar1.Position:=hi(v)
else

TrackBar1.Position:=hi(v shr 16);
end;


end.



函数说明:

waveOutSetVolume
第一个参数是波形文件输出设备标识符;
第二个参娄是音量大小。这是一个32位的整数,低16位表示左声道的音量,
高16位表示右声道的音量。

waveOutGetVolume
第一个参数是波形文件输出设备标识符;
第二个参数是一个32位整数的指针。
//****************************************************************//
 
下面的网址说的很详细,实现了控制混合器。
http://www.powerba.com/develop/delphi/article/20010615001.htm
 
详细的解答:
//谢谢了。
为了便于大家以后查询,将原文贴于以下
Delphi 4下编写Audio Mixer Control
Windows95下的 Volume Control(音量控制器)是一个很常用的小程序。但控制器太多摆不
下,而且回放和录音之间要经常切换,很不方便。一些朋友编写多媒体播放器,是否想过加
个内置混音器呢?你有没有想过自己编写混音器程序呢?下面具体的编写方法。

一、混音器的结构

首先简单介绍混音器的结构。混音器由多个destination(目的单元)组成,如Playback(回
放)、Recording(录音)、Voice command(语音命令)等等。 而每个destination又由多个Con
nections(连接设备), 如回放下有CD Audio、MIDI 、Wave等等。每条 Connection 联系着
一个或以上的Control(控制器)。Control是混音器的关键,有Volume Control(音量控制器)、
Mute Control(静音控制器)、Meter Control(仪表控制器)等等。

以下是Mixer 的结构及调用的函数

Mixer (mixerGetNumDevs返回mixer 的个数, 后要用Mixeropen打开混音器)

|

Destinations (destinations should be for example: Playback, Recording and Voic
e commands)

* | (The number of destinations return by mixerGetDevCaps)

* |--Destination[0] (调用 mixerGetLineInfo 取得Destination连接的Connections和Controls)

* | |

* | |--Controls (controls of the line, ex: Master volume, master mute)

* | | | (调用MixerGetLineControls 取得 Controls)

* | | |--Control[0]

* | | |--Control[1]

* | | |--Control[..]

* | |

* | |--Connections (ex: Wave, MIDI, CD Audio, Line-In,...)

* | |

* | |--Connection[0]

* | | |--Controls (here can be volume and mute)

* | | | (调用MixerGetLineControls 取得 Controls)

* | | |--Control[0] (ex:Wave Volume)

* | | |--Control[1] (ex:Wave Mute)

* | | |--Control[..] (ex:Wave Meter)

* | |

* | |--Connection[1]

* | |--Connection[..]

* |

* |--Destination[1]

* |--Destination[..]



一步一步的先后取得Destinations、Connections,但最终的目的是取得各种的Controls,

以后的音量、静音的控制都要调用Controls。所以要保存Controls的数据。本程序用一

个三维的动态数组保存Controls。方便以后调用。



二、本程序的函数的作用

getvolume 取得音量, setvolume设置音量;

getmute取得设备是否静音, setmute是设备静音。

Getpeak取得设备的peak(振幅)

五个程序都是填写Tmixercontroldetails类型调用 mixergetcontroldetails,mixerse
tcontroldetails。

三、关于mixer 的message及Callback Function

Mixer 提供

MM_MIXM_CONTROL_CHANGE

MM_MIXM_LINE_CHANGE

两个message要在调用 mixeropen 设置Callback Function

unit Unit2;


//Written by David Jiang(江天送)

//july 25th. 1999

interface

uses

Windows, Messages, SysUtils, Classes, Graphics, Controls,

Forms, Dialogs,StdCtrls, ComCtrls, mmsystem, Buttons, ExtCtrls;


type Tvolume=record

left,right:word;


end;



type

TForm2 = class(TForm)

Lines: TComboBox;


Controls: TComboBox;


Label1: TLabel;


lmute: TLabel;


lmeter: TLabel;


LVolume: TTrackBar;


Rvolume: TTrackBar;


cmute: TCheckBox;


CheckBox1: TCheckBox;


About: TSpeedButton;


BExit: TSpeedButton;


RProgressBar: TProgressBar;


Timer1: TTimer;


procedure FormCreate(Sender: TObject);


procedure getlinecontrol;


procedure LinesChange(Sender: TObject);


procedure ControlsChange(Sender: TObject);


procedure LVolumeChange(Sender: TObject);


procedure cmuteClick(Sender: TObject);


procedure RvolumeChange(Sender: TObject);


procedure AboutClick(Sender: TObject);


procedure BExitClick(Sender: TObject);


procedure Timer1Timer(Sender: TObject);


procedure FormClose(Sender: TObject;
var

Action: TCloseAction);




private

{ Private declarations }

procedure mmixer(var msg:Tmessage);


public

{ Public declarations }

end;



function getvolume(control:Pmixercontrol;var

volume:Tvolume):boolean;


function setvolume(control:Pmixercontrol;


volume:Tvolume):boolean;


function setmute(control:Pmixercontrol;


mute:integer):boolean;


function getmute(control:Pmixercontrol;var

mute:integer):boolean;


function getpeak(control:Pmixercontrol;var

peak:integer):boolean;


procedure Fillstruct(control:Pmixercontrol;var

Cdetails:Tmixercontroldetails);


var

Form2: TForm2;


fmixerhandle:hmixer;
//混音器的句柄

mcontrols:array of array of array of PMixerControl;


line:array of Tstringlist;


peaknum:integer;
//meter mcontrols的位置

implementation



{$R *.DFM}



procedure Tform2.mmixer(var msg:Tmessage);


var

volume:Tvolume;


mute:integer;


begin


if msg.Msg=MM_MIXM_CONTROL_CHANGE then


begin


if mcontrolS[lines.itemindex][controls.itemindex]

[0].dwcontrolID=msg.LParam then


if getvolume(mcontrolS[lines.itemindex]

[controls.itemindex][0],volume) then


begin


Rvolume.Position :=-volume.right;


Lvolume.Position :=-volume.left;


end;



if mcontrolS[lines.itemindex][controls.itemindex]

[1].dwcontrolid=msg.LParam then


if getmute(mcontrolS[lines.itemindex]

[controls.itemindex][1],mute) then


cmute.Checked:=mute=1;


end;



end;



procedure TForm2.FormCreate(Sender: TObject);


begin


getlinecontrol;


lines.ItemIndex :=0;


controls.Items:=line[lines.ItemIndex];


controls.ItemIndex :=0;


controls.OnChange (sender);


end;





procedure Tform2.getlinecontrol;


var

mixerID:integer;
//混音器的ID

FMixerCaps:TMixerCaps;


n,j,k,i:integer;


ml,ml2:TMIXERLINE;


MLC:TMixerLineControls;


P:PMixerControl;


begin


if mixerGetNumDevs=0 then
exit;
//如没有混合器装置,退出

fmixerhandle:=0;


mixerID:=0;


mixerOpen (@FMixerHandle,mixerID,AllocateHWnd(mmixer),

0,CALLBACK_WINDOW OR MIXER_OBJECTF_MIXER);


//打开混音器

mixerGetDevCaps (mixerID,@FMixerCaps,SizeOf (TMixerCaps));


//返回混音器的兼容性

setlength(line,fmixercaps.cDestinations);


setlength(mcontrols,fmixercaps.cDestinations );


for i:=0 to fmixercaps.cDestinations-1do


begin


ml.dwDestination:=i;


ml.cbStruct :=sizeof(tMIXERLINE);


mixerGetLineInfo(fmixerhandle,@ml,

MIXER_GETLINEINFOF_DESTINATION);


//取得混音器的Destinations

line:=tstringlist.Create


setlength(mcontrols,ml.cconnections);


n:=0;


if ml.cControls>1 then


begin


n:=1;


setlength(mcontrols,ml.cconnections+1);


MLC.cbStruct:=SizeOf(MLC);


MLC.dwLineID:=ml.dwLineID;


MLC.cControls:=ml.cControls;


MLC.cbmxctrl:=SizeOf(TMixerControl);


GetMem (P,SizeOf(TMixerControl)*ml.cControls);


MLC.pamxctrl:=P;


MixerGetLineControls(fMixerHandle,@MLC,

MIXER_GETLINECONTROLSF_ALL);


setlength(mcontrols[0],ml.cControls);


line.Add(p^.szname);
//Master Volume

For k:=0 to ml.cControls-1do


begin


mcontrols[0][k]:=p;


mcontrols[0][0].Metrics.dwReserved[k+1]:=1;


inc(p);


end;



end;



lines.Items.Add(ml.szName);


ML2.cbStruct:=SizeOf(TMixerLine);


ML2.dwDestination:=ml.dwDestination


for j:=0 to ml.cConnections -1do


begin


ML2.dwSource:=j;


MixerGetLineInfo (fmixerHandle,@ML2,

MIXER_GETLINEINFOF_SOURCE);


MLC.cbStruct:=SizeOf(MLC);


MLC.dwLineID:=ml2.dwLineID;


MLC.cControls:=ml2.cControls;


MLC.cbmxctrl:=SizeOf(TMixerControl);


GetMem (P,SizeOf(TMixerControl)*ml2.cControls);


MLC.pamxctrl:=P;


MixerGetLineControls(fMixerHandle,@MLC,

MIXER_GETLINECONTROLSF_ALL);


setlength(mcontrols[j+n],ml2.cControls);


For k:=0 to ml2.cControls-1do


begin


if p.dwControlType=MIXERCONTROL_CONTROLTYPE_VOLUME

then
line.add(p^.szName);


mcontrols[j+n][k]:=p;


mcontrols[j+n][0].Metrics.dwReserved[k+1]:=1;


inc(p);


end;
//取得混音器线路的控制器

end;



end;



end;





procedure Fillstruct(control:Pmixercontrol;var

Cdetails:Tmixercontroldetails);


begin


cdetails.cbStruct:=sizeof(cdetails);


cdetails.dwControlID:=control.dwControlID


cdetails.cbDetails:=sizeof(integer);


cdetails.hwndOwner :=0;


end;



function getpeak(control:Pmixercontrol;var

peak:integer):boolean;


var

details:TMIXERCONTROLDETAILSSIGNED;


cdetails:TMIXERCONTROLDETAILS;


begin


result:=false;


if control.dwControlType <>

MIXERCONTROL_CONTROLTYPE_PEAKMETER then
exit;


cdetails.cChannels :=1;


cdetails.paDetails:=@details;


fillstruct(control,cdetails);


result:=MIXERGETCONTROLDETAILS(fmixerhandle,

@cdetails,MIXER_GETCONTROLDETAILSF_VALUE)=0;


peak:=abs(details.LValue) div 180;


end;





function setvolume(control:Pmixercontrol;


volume:Tvolume):boolean;


var

details:array [0..30] of Integer;


cdetails:TMIXERCONTROLDETAILS;


begin


fillstruct(control,cdetails);


cdetails.cChannels :=2;


cdetails.paDetails:=@details;


details[0]:=volume.left;


details[1]:=volume.right;


result:=MIXERSETCONTROLDETAILS(fmixerhandle,

@cdetails,MIXER_GETCONTROLDETAILSF_VALUE)=0;


end;





function getvolume(control:Pmixercontrol;var

volume:Tvolume):boolean;


var

details:array [0..30] of Integer;


cdetails:TMIXERCONTROLDETAILS;


begin


fillstruct(control,cdetails);


cdetails.cChannels :=2;


cdetails.paDetails:=@details;


result:=MIXERGETCONTROLDETAILS(fmixerhandle,

@cdetails,MIXER_GETCONTROLDETAILSF_VALUE)=0;


volume.left:=details[0];


volume.right:=details[1];


end;



function setmute(control:Pmixercontrol;


mute:integer):boolean;


var

cdetails:Tmixercontroldetails;


details:array [0..30] of Integer;


begin


fillstruct(control,cdetails);


cdetails.cChannels :=1;


cdetails.paDetails:=@details;


details[0]:=mute;


result:=MIXERSETCONTROLDETAILS(fmixerhandle,

@cdetails,MIXER_GETCONTROLDETAILSF_VALUE)=0;


end;



function getmute(control:Pmixercontrol;var

mute:integer):boolean;


var

cdetails:Tmixercontroldetails;


details:array [0..30] of Integer;


begin


fillstruct(control,cdetails);


cdetails.cChannels :=1;


cdetails.cMultipleItems:=0;


cdetails.paDetails:=@details;


result:=MIXERGETCONTROLDETAILS(fmixerhandle,

@cdetails,MIXER_GETCONTROLDETAILSF_VALUE)=0;


mute:=details[0];


end;





procedure TForm2.LinesChange(Sender: TObject);


begin


controls.Items:=line[lines.ItemIndex];


if controls.ItemIndex =-1 then


controls.ItemIndex :=0;


end;





procedure TForm2.ControlsChange(Sender: TObject);


var

mute,k,j:integer;


volume:Tvolume;


begin


lmute.Visible :=false;


lmeter.Visible :=false;


k:=lines.ItemIndex;j:=controls.ItemIndex;


IF mcontrols[k][j][0].Metrics.dwReserved[2]=1 then


begin


lmute.Visible:=mcontrols[k][j][1].dwcontroltype

=MIXERCONTROL_CONTROLTYPE_MUTE;


lmeter.Visible:=mcontrols[k][j][1].dwcontroltype

=MIXERCONTROL_CONTROLTYPE_PEAKMETER;


if lmeter.Visible then
peaknum:=1;


end;



cmute.Enabled :=lmute.Visible


IF mcontrols[k][j][0].Metrics.dwReserved[3]=1 then


begin


lmeter.Visible:=mcontrols[k][j][2].dwcontroltype

=MIXERCONTROL_CONTROLTYPE_PEAKMETER;


if lmeter.Visible then
peaknum:=2;


end;



if getvolume(mcontrols[k][j][0],volume) then


begin


Rvolume.Position :=-volume.right;


Lvolume.Position :=-volume.left;


end;



if getmute(mcontrols[k][j][1],mute) then


cmute.Checked :=mute=1;


RProgressbar.Visible :=lmeter.Visible;;


timer1.Enabled:=lmeter.Visible;


end;





procedure TForm2.LVolumeChange(Sender: TObject);


var volume:tvolume;


begin


if checkbox1.Checked then
Rvolume.Position :=Lvolume.Position


volume.right :=-Rvolume.Position;


volume.left:=-Lvolume.Position


setvolume(mcontrolS[lines.itemindex][controls.itemindex][0],

volume);


end;





procedure TForm2.cmuteClick(Sender: TObject);


var mute:integer;


begin


if cmute.checked then
mute:=1 else
mute:=0;


setmute(mcontrolS[lines.itemindex][controls.itemindex][1],mute);


end;





procedure TForm2.RvolumeChange(Sender: TObject);


begin


if checkbox1.Checked then
Lvolume.Position :=Rvolume.Position


Lvolume.OnChange (sender);


end;





procedure TForm2.AboutClick(Sender: TObject);


begin


showmessage('Mixer Demo version 1.0 '+chr(13)

+'Written by David Jiang');


end;





procedure TForm2.BExitClick(Sender: TObject);


begin


close;


end;





procedure TForm2.Timer1Timer(Sender: TObject);


var peak:integer;


begin


IF mcontrols[lines.itemindex][controls.itemindex]

[0].Metrics.dwReserved[peaknum+1]=1 then


if getpeak(mcontrols[lines.itemindex][controls.itemindex]

[peaknum],peak) then


Rprogressbar.Position :=peak;


end;





procedure TForm2.FormClose(Sender: TObject;
var Action: TCloseAction);


begin


mixerclose(fmixerhandle);


end;


end.

 
ljp686,你好
不知你对本问题提出的答案是否是你的佳作,我有两个疑难想请教:
1。是否每个destination下既有Controls 又有Connections ,从结构图上看是这样的

2。TTrackBar的最大值设置为多大,或者说:左右声道的音量最大值是多少?

3。对于 procedure Fillstruct(control:Pmixercontrol;var Cdetails:Tmixercontroldetails);

我不知道是什么作用,可以解释一下吗?

//如果可以提供回答,请直接回复到qiguangping@263.net
//如果你知道作者是谁,请告知我,

谢谢

 
請問可以控制Volume Control->Options->Properties->Recording這個選項嗎?
我想控制這個選項的Mixer立體混音的音量, 盼回覆, 多謝.
 
后退
顶部