全國最多中醫師線上諮詢網站-台灣中醫網
發文 回覆 瀏覽次數:1984
推到 Plurk!
推到 Facebook!

Volume Control(音量控制器)

 
cmf
尊榮會員


發表:84
回覆:918
積分:1032
註冊:2002-06-26

發送簡訊給我
#1 引用回覆 回覆 發表時間:2003-09-11 13:23:59 IP:61.218.xxx.xxx 未訂閱
資料來源: 本站原创及翻译内容保留版权,欢迎转贴,转贴时请注明转自哈巴狗的小窝 Volume Control(音量控制器)是一个很常用的小程序。但控制器太多摆不下,而且回放和录音之间要经常切换,很不方便。一些朋友编写多媒体播放器,是否想过加个内置混音器呢?你有没有想过自己编写混音器程序呢?下面具体的编写方法。
一、混音器的结构       首先简单介绍混音器的结构。混音器由多个destination(目的单元)组成,如Playback(回放)、Recording(录音)、Voice command(语音命令)等等。 而每个destination又由多个Connections(连接设备), 如回放下有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 Voice 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,mixersetcontroldetails。    三、关于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-1 do     begin     ml.dwDestination:=i;     ml.cbStruct :=sizeof(tMIXERLINE);     mixerGetLineInfo(fmixerhandle,@ml,     MIXER_GETLINEINFOF_DESTINATION);     //取得混音器的Destinations     line[i]:=tstringlist.Create ;     setlength(mcontrols[i],ml.cconnections);     n:=0;     if ml.cControls>1 then     begin     n:=1;     setlength(mcontrols[i],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[i][0],ml.cControls);     line[i].Add(p^.szname); //Master Volume     For k:=0 to ml.cControls-1 do     begin     mcontrols[i][0][k]:=p;     mcontrols[i][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 -1 do     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[i][j n],ml2.cControls);     For k:=0 to ml2.cControls-1 do     begin     if p.dwControlType=MIXERCONTROL_CONTROLTYPE_VOLUME     then line[i].add(p^.szName);     mcontrols[i][j n][k]:=p;     mcontrols[i][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.        
發表人 - cmf 於 2003/09/11 13:34:57
------
︿︿
系統時間:2024-04-29 18:16:20
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!