有關音量輸出的問題... |
尚未結案
|
jenpeter
一般會員 發表:39 回覆:37 積分:15 註冊:2002-08-14 發送簡訊給我 |
|
3CS
一般會員 發表:5 回覆:9 積分:2 註冊:2003-07-31 發送簡訊給我 |
|
chenliyan163
一般會員 發表:30 回覆:30 積分:12 註冊:2003-09-15 發送簡訊給我 |
一、混音器的结构 首先简单介绍混音器的结构。混音器由多个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.
|
japhenchen
高階會員 發表:51 回覆:444 積分:184 註冊:2003-07-23 發送簡訊給我 |
上面的方法好複雜,好複雜,好複雜~~~~~~~~程式也沒縮排,我眼睛都看花了! 請各位下載一套DSPACK 2.31的元件,網址在後面自己點下載吧!
http://www.progdigy.com/ 照著範例做一個可以播放VCD的程式,很簡單,灰熊簡單,簡單到會堆積木的程式設計師也可以簡單辦到,一個FILTERGRAPH跟VIDEOWINDOW的元件,在ONFORMSHOW里加上三行程式就可以完成一個VCD/MP3/WMV/WMA/ASF/WAV/MIDI/CD/DVD(是真的,騙你砍頭)的播放程式!
FILTERGRAPH.ACTIVATE:=TRUE; FILTERGRAPH.RENDERFILE('E:\MUSIC\AV0001.DAT'); FILTERGRAPH.PLAY;//動了動了!(如果是玩DVD,程式如下) var Status : TAMDVDRenderStatus; DvdCmd: IDvdCmd; HR: HRESULT; begin FilterGraph.Active := true; FilterGraph.RenderDvd(Status, 'E:\VIDEO_TS.IFO'); FilterGraph.Play;VCD怎麼做到人聲跟樂聲分離呢?更簡單,啥記憶体複製?音量調節全都免了,做法如下 (DVD的做法就大同小異,只是調用的FILTER不同而已) 1、在剛剛寫出來的VCD播放器中,在DESIGN階段加上一個DSPACK的TFILTER元件,元件屬性最上面有一個叫做BASEFILTER的列舉項,點進去後在FILTERS里選擇DirectShow Filters,展開後再找到Mpeg Audio Decoder,按ok~ 2、在你的播放器里加一個可以設定聲道的RADIOGROUP多選項,ITEMS就自己加入"全聲道","僅放第一聲道","僅放第二聲道"三項(VCD只有二條聲道,DVD有四條),在ONCLICK的事件里設定以下程式碼,即可解決人聲去除的問題!左右平衡,就像KTV機一樣! procedure TForm1.RadioGroup1Click(Sender: TObject); VAR GS2 : IMpegAudioDecoder; SCNT : cardinal; begin scnt:=radiogroup1.ItemIndex; if succeeded(Filter1.QueryInterface(IMpegAudioDecoder,GS2)) then gs2.put_dualmode(scnt); end;3、後面沒啦!就這上面短短的幾行就可以搞定,誰說一定要懂得高技術mp3>decode to PCM>記憶体複製>音量調整....弄的人聲去除了,出現左右聲不平衡的缺憾?用WINDOWS內建的DIRECTSHOW,一樣可以辦的到! DIRECTSHOW還有什麼特異功能?多了~多了~~多到數不完~~~~加上二個FILTER,就可以讓你邊播邊唱,唱出來的歌聲還有ECHO唷!(改天再討論這功能吧),還有讓你簡單的寫出一套不用安裝REALONE就可以播放RM格式的電影檔,RA格式的音樂檔,RAM串流檔(程式啥都不用改,只要在系統里加入REGSVR32進一個REALMEDIASPLITTER.AX的過濾器就可以使用,在網上可以下載的到) 最近在網上找到一個AX檔,可以把MP3歌曲里的人的人聲給幹掉唷!(VOCAL REMOVER FOR DIRECTX),做法跟VCD去除人聲的方法相同,加入TFILTER的元件,BASEFILTER里找到VOCALREMOVER的過濾器 我不懂,不懂,不懂....所以我才來 |
japhenchen
高階會員 發表:51 回覆:444 積分:184 註冊:2003-07-23 發送簡訊給我 |
對了,DSPACK是成套元件,不是單一套件~用法很簡單的~安裝有點小麻煩 DIVX就是標準的DIRECTSHOW的編解碼器,所以有安裝DIVX的電腦,也可以用剛剛所寫的播放器來播DIVX的AVI電影檔 還有啊,像在網上可以找的到的各式各樣的FOR WindowsMediaPlayer8/9的Plugin,安裝之後就也會自動在DirectShow寫出來的播放器中被直接調入使用唷,程式設計師不用寫任何程式就可以,像DVD轉DIVX後,有的會留下SRT字幕,也可以被用在剛剛寫的程式,有心一點,還可以調WMP的DSP聲音效果動畫出來用,不難的~ 我不懂,不懂,不懂....所以我才來ktop學工夫
|
japhenchen
高階會員 發表:51 回覆:444 積分:184 註冊:2003-07-23 發送簡訊給我 |
編寫DIRECTSHOW的程式設計師不可以沒有這套工具,GRAPHEDIT
http://www.microsoft.com/downloads/details.aspx?familyid=07399584-92df-4849-871e-1eb3424f8b91&languageid=f49e8428-7071-4979-8a67-3cffcb0c2524&displaylang=en
附在上面連結里的微軟的DIRECTTSHOW9 SDK包里,可以直接使用 用法簡單,FILE->OPEN->找個DAT、MPG、AVI、MP3,連BMP、JPG都可以,打開後會看到一堆關係圖,這就是播放這些媒体檔時所有(系統自動產生的)被用到過濾器(FILTER),一堆過濾器產生的表,就叫做FILTER GRAPH,建立這個FITLER GRAPH的元件(WINDOWS系統里的),就叫做GRAPHBUILDER,連結二個或以上的FILTER的線就是PIN(大陸用語叫梢)......(以後大家一塊研究吧) 我不懂,不懂,不懂....所以我才來ktop學工夫
|
chungho_chang
一般會員 發表:16 回覆:7 積分:4 註冊:2003-09-19 發送簡訊給我 |
|
chfamy
中階會員 發表:87 回覆:161 積分:54 註冊:2002-05-03 發送簡訊給我 |
剛好最近在用該元件,記下安裝步驟,希望對大家有所幫助,如有錯誤敬請指正,謝謝。 http://www.progdigy.com/dspack/ DSPack 2.31 (2003-06-01)
------------------------------------------------------------------------------------
元件安裝步驟:
1.執行DSPACK231進行元件安裝。
2.點選功能表上的「Tools→Environment Options→Library頁籤」,檢查「Library Path」是
否包含「C:\Program Files\DSPack\packages」、「C:\Program Files\DSPack\src」、「C:
\Program Files\DSPack\lib」、「C:\Program Files\DSPack\src\DSPack」及「C:\Program
Files\DSPack\src\DirectX9」目錄,如果不否包該目錄,以「Add」按鈕加入該目錄資料。
3.點選功能表上的「File→Open」,開啟「Delphi Package」檔案,「DSPackDesign_D6.dpk」
,點選「Compile」及「Install」按鈕,進行DSPack 2.31元件安裝。
3.出現「Information」視窗,點選「Ok」按鈕。
4.點選功能表上的「File→Save All」完成元件安裝,元件頁標多出「DSPack」。
------------------------------------------------------------------------------------
|
northguy
一般會員 發表:1 回覆:12 積分:2 註冊:2004-02-26 發送簡訊給我 |
引言: 上面的方法好複雜,好複雜,好複雜~~~~~~~~程式也沒縮排,我眼睛都看花了! 請各位下載一套DSPACK 2.31的元件,網址在後面自己點下載吧! http://www.progdigy.com/ 照著範例做一個可以播放VCD的程式,很簡單,灰熊簡單,簡單到會堆積木的程式設計師也可以簡單辦到,一個FILTERGRAPH跟VIDEOWINDOW的元件,在ONFORMSHOW里加上三行程式就可以完成一個VCD/MP3/WMV/WMA/ASF/WAV/MIDI/CD/DVD(是真的,騙你砍頭)的播放程式!FILTERGRAPH.ACTIVATE:=TRUE; FILTERGRAPH.RENDERFILE('E:\MUSIC\AV0001.DAT'); FILTERGRAPH.PLAY;//動了動了!(如果是玩DVD,程式如下)var Status : TAMDVDRenderStatus; DvdCmd: IDvdCmd; HR: HRESULT; begin FilterGraph.Active := true; FilterGraph.RenderDvd(Status, 'E:\VIDEO_TS.IFO'); FilterGraph.Play;VCD怎麼做到人聲跟樂聲分離呢?更簡單,啥記憶体複製?音量調節全都免了,做法如下 (DVD的做法就大同小異,只是調用的FILTER不同而已) 1、在剛剛寫出來的VCD播放器中,在DESIGN階段加上一個DSPACK的TFILTER元件,元件屬性最上面有一個叫做BASEFILTER的列舉項,點進去後在FILTERS里選擇DirectShow Filters,展開後再找到Mpeg Audio Decoder,按ok~ 2、在你的播放器里加一個可以設定聲道的RADIOGROUP多選項,ITEMS就自己加入"全聲道","僅放第一聲道","僅放第二聲道"三項(VCD只有二條聲道,DVD有四條),在ONCLICK的事件里設定以下程式碼,即可解決人聲去除的問題!左右平衡,就像KTV機一樣!procedure TForm1.RadioGroup1Click(Sender: TObject); VAR GS2 : IMpegAudioDecoder; SCNT : cardinal; begin scnt:=radiogroup1.ItemIndex; if succeeded(Filter1.QueryInterface(IMpegAudioDecoder,GS2)) then gs2.put_dualmode(scnt); end;3、後面沒啦!就這上面短短的幾行就可以搞定,誰說一定要懂得高技術mp3>decode to PCM>記憶体複製>音量調整....弄的人聲去除了,出現左右聲不平衡的缺憾?用WINDOWS內建的DIRECTSHOW,一樣可以辦的到! DIRECTSHOW還有什麼特異功能?多了~多了~~多到數不完~~~~加上二個FILTER,就可以讓你邊播邊唱,唱出來的歌聲還有ECHO唷!(改天再討論這功能吧),還有讓你簡單的寫出一套不用安裝REALONE就可以播放RM格式的電影檔,RA格式的音樂檔,RAM串流檔(程式啥都不用改,只要在系統里加入REGSVR32進一個REALMEDIASPLITTER.AX的過濾器就可以使用,在網上可以下載的到) 最近在網上找到一個AX檔,可以把MP3歌曲里的人的人聲給幹掉唷!(VOCAL REMOVER FOR DIRECTX),做法跟VCD去除人聲的方法相同,加入TFILTER的元件,BASEFILTER里找到VOCALREMOVER的過濾器 我不懂,不懂,不懂....所以我才來>>< face="Verdana, Arial, Helvetica"> |
northguy
一般會員 發表:1 回覆:12 積分:2 註冊:2004-02-26 發送簡訊給我 |
引言: 上面的方法好複雜,好複雜,好複雜~~~~~~~~程式也沒縮排,我眼睛都看花了! 請各位下載一套DSPACK 2.31的元件,網址在後面自己點下載吧! http://www.progdigy.com/ 照著範例做一個可以播放VCD的程式,很簡單,灰熊簡單,簡單到會堆積木的程式設計師也可以簡單辦到,一個FILTERGRAPH跟VIDEOWINDOW的元件,在ONFORMSHOW里加上三行程式就可以完成一個VCD/MP3/WMV/WMA/ASF/WAV/MIDI/CD/DVD(是真的,騙你砍頭)的播放程式!FILTERGRAPH.ACTIVATE:=TRUE; FILTERGRAPH.RENDERFILE('E:\MUSIC\AV0001.DAT'); FILTERGRAPH.PLAY;//動了動了!(如果是玩DVD,程式如下)var Status : TAMDVDRenderStatus; DvdCmd: IDvdCmd; HR: HRESULT; begin FilterGraph.Active := true; FilterGraph.RenderDvd(Status, 'E:\VIDEO_TS.IFO'); FilterGraph.Play;VCD怎麼做到人聲跟樂聲分離呢?更簡單,啥記憶体複製?音量調節全都免了,做法如下 (DVD的做法就大同小異,只是調用的FILTER不同而已) 1、在剛剛寫出來的VCD播放器中,在DESIGN階段加上一個DSPACK的TFILTER元件,元件屬性最上面有一個叫做BASEFILTER的列舉項,點進去後在FILTERS里選擇DirectShow Filters,展開後再找到Mpeg Audio Decoder,按ok~ 2、在你的播放器里加一個可以設定聲道的RADIOGROUP多選項,ITEMS就自己加入"全聲道","僅放第一聲道","僅放第二聲道"三項(VCD只有二條聲道,DVD有四條),在ONCLICK的事件里設定以下程式碼,即可解決人聲去除的問題!左右平衡,就像KTV機一樣!procedure TForm1.RadioGroup1Click(Sender: TObject); VAR GS2 : IMpegAudioDecoder; SCNT : cardinal; begin scnt:=radiogroup1.ItemIndex; if succeeded(Filter1.QueryInterface(IMpegAudioDecoder,GS2)) then gs2.put_dualmode(scnt); end;3、後面沒啦!就這上面短短的幾行就可以搞定,誰說一定要懂得高技術mp3>decode to PCM>記憶体複製>音量調整....弄的人聲去除了,出現左右聲不平衡的缺憾?用WINDOWS內建的DIRECTSHOW,一樣可以辦的到! DIRECTSHOW還有什麼特異功能?多了~多了~~多到數不完~~~~加上二個FILTER,就可以讓你邊播邊唱,唱出來的歌聲還有ECHO唷!(改天再討論這功能吧),還有讓你簡單的寫出一套不用安裝REALONE就可以播放RM格式的電影檔,RA格式的音樂檔,RAM串流檔(程式啥都不用改,只要在系統里加入REGSVR32進一個REALMEDIASPLITTER.AX的過濾器就可以使用,在網上可以下載的到) 最近在網上找到一個AX檔,可以把MP3歌曲里的人的人聲給幹掉唷!(VOCAL REMOVER FOR DIRECTX),做法跟VCD去除人聲的方法相同,加入TFILTER的元件,BASEFILTER里找到VOCALREMOVER的過濾器 我不懂,不懂,不懂....所以我才來>>< face="Verdana, Arial, Helvetica"> |
northguy
一般會員 發表:1 回覆:12 積分:2 註冊:2004-02-26 發送簡訊給我 |
|
japhenchen
高階會員 發表:51 回覆:444 積分:184 註冊:2003-07-23 發送簡訊給我 |
既然是用DSPACK來處理ISpecifyPropertyPages,那我回答的也不會難到那里去 1、假設你已經會用DSPACK來播放MPEG檔了,那你跟去除人聲的方法一樣,放一個TFILTER到你的程式上去,指定FILTERGRAPH到你程式主要處理媒体的FilterGraph上去,在BASEFILTER選項中,指定到DirectShow Filter群中的Mpeg Audio Decoder,然後ok 2、在程式里看要放一個按鈕,或者熱鍵,隨人,加上一段
var MpegAudioDecoder: IMpegAudioDecoder;
begin
if succeeded(Filter1.QueryInterface(IMpegAudioDecoder,MpegAudioDecoder)) then
ShowFilterPropertyPage(self.handle, Filter1.BaseFilter.CreateFilter);
紅色的部份就是我剛要各位加上去的那個TFILTER項,只要正確指定,就可以使用
|
japhenchen
高階會員 發表:51 回覆:444 積分:184 註冊:2003-07-23 發送簡訊給我 |
|
northguy
一般會員 發表:1 回覆:12 積分:2 註冊:2004-02-26 發送簡訊給我 |
非常感谢答复
引言: 既然是用DSPACK來處理ISpecifyPropertyPages,那我回答的也不會難到那里去 1、假設你已經會用DSPACK來播放MPEG檔了,那你跟去除人聲的方法一樣,放一個TFILTER到你的程式上去,指定FILTERGRAPH到你程式主要處理媒体的FilterGraph上去,在BASEFILTER選項中,指定到DirectShow Filter群中的Mpeg Audio Decoder,然後ok 2、在程式里看要放一個按鈕,或者熱鍵,隨人,加上一段 var MpegAudioDecoder: IMpegAudioDecoder; begin if succeeded(Filter1.QueryInterface(IMpegAudioDecoder,MpegAudioDecoder)) then ShowFilterPropertyPage(self.handle, Filter1.BaseFilter.CreateFilter); 紅色的部份就是我剛要各位加上去的那個TFILTER項,只要正確指定,就可以使用 |
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |