在 Delphi 下使用 DirectSound (9): 效果器初步及 IDirectSoundFXGargle8 效果器
生活随笔
收集整理的這篇文章主要介紹了
在 Delphi 下使用 DirectSound (9): 效果器初步及 IDirectSoundFXGargle8 效果器
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
只有使用 IDirectSoundBuffer8 的次緩沖區才能設置"特效", 主緩沖區主要負責的是混音和處理 3D 效果.
IDirectSoundBuffer8(非 IDirectSoundBuffer) 支持以下效果器:
IDirectSoundFXChorus8 //合唱; 微調原生與回聲的延遲 IDirectSoundFXCompressor8 //壓縮; 壓縮某些振幅 IDirectSoundFXDistortion8 //失真; 將波形頂部修改為方形或鋸齒形 IDirectSoundFXEcho8 //回聲; 重復并衰減回聲 IDirectSoundFXFlanger8 //鑲邊; 延遲回聲 IDirectSoundFXGargle8 //漱口; 有人叫它咕嘟效果 IDirectSoundFXI3DL2Reverb8 //環境混響; 房間、大廳等 IDirectSoundFXParamEq8 //均衡; 縮放不同頻率的信號 IDirectSoundFXWavesReverb8 //混響; DirectX Media Objects(DMOs), 是微軟從 Waves 購買的聲音處理技術
使用步驟:
1、通過 IDirectSoundBuffer8 的 SetFX() 方法關聯特效, 這個過程主要是給 SetFX() 方法的參數準備 TDSEffectDesc 結構數組;
2、通過 IDirectSoundBuffer8 的 GetObjectInPath() 方法獲取特效對象;
3、通過特效對象的 SetAllParameters() 方法設置特效參數.
9 個特效對象都只有兩個方法: GetAllParameters()、SetAllParameters(), 兩方法的參數都是結構體(各不相同).
{給 IDirectSoundBuffer8 關聯特效; 不能在緩沖區鎖定或播放時使用:} function SetFX(dwEffectsCount: DWORD; //特效數目, 即第二個參數 pDSFXDesc 的大小pDSFXDesc: PDSEffectDesc; //TDSEffectDesc 結構的數組pdwResultCodes: PDWORD //接收設置結果, 不需要則給 nil ): HResult; stdcall;//可以使用 SefFX(0, nil, nil) 刪除緩沖區的所有特效.{SetFX() 方法用到的結構體:} TDSEffectDesc = packed recorddwSize : DWORD; //結構大小dwFlags : DWORD; //處理標志; 一般給 0guidDSFXClass : TGUID; //指定要使用的效果dwReserved1 : DWORD_PTR; //未使用dwReserved2 : DWORD_PTR; //未使用 end;//DSEffectDesc.dwFlags DSFX_LOCHARDWARE = $00000001; //使用硬件處理效果; 這其實在 Direct9.0 還不支持 DSFX_LOCSOFTWARE = $00000002; //使用軟件處理效果; 同默認 0 //默認//DSEffectDesc.guidDSFXClass, 這分別是上面九個接口對應的 GUID 查詢標識: GUID_DSFX_STANDARD_CHORUS GUID_DSFX_STANDARD_COMPRESSOR GUID_DSFX_STANDARD_DISTORTION GUID_DSFX_STANDARD_ECHO GUID_DSFX_STANDARD_FLANGER GUID_DSFX_STANDARD_GARGLE GUID_DSFX_STANDARD_I3DL2REVERB GUID_DSFX_STANDARD_PARAMEQ GUID_DSFX_WAVES_REVERB {從 IDirectSoundBuffer8 獲取特效對象的方法} function GetObjectInPath(const rguidObject: TGUID; //對象查詢標識, GUID_DSFX_ ...dwIndex: DWORD; //該特效在 SetFX() 安排特效數組時的索引 const rguidInterface: TGUID; //對象的唯一標識, IID_IDirectSoundFX ... 或 IDirectSoundFX ...out ppObject //返回要獲取的特效接口 ): HResult; stdcall;{IDirectSoundFXGargle8.SetAllParameters() 需要結構體} TDSFXGargle = packed recorddwRateHz: DWORD; //頻率; 取值范圍 1..1000, 默認 20dwWaveShape: DWORD; //波形; 三角波(0)、方波(1) end;//TDSFXGargle.dwRateHz 取值范圍, 默認是 20 DSFXGARGLE_RATEHZ_MIN = 1; // DSFXGARGLE_RATEHZ_MAX = 1000; //DSFXGARGLE_WAVE_TRIANGLE = 0; //三角波 DSFXGARGLE_WAVE_SQUARE = 1; //方波
為讓代碼更簡潔, 又把前面自定義的 ReadWave 該為了 ReadWave2 (增加了一個 OpenDialog 方法):
unit ReadWave2;interfaceuses Windows, Classes, SysUtils, MMSystem, Dialogs;type TReadWave = class privateFFileHandle: HMMIO;FFormat: TWaveFormatEx;FSize: DWORD;function GetFormatAndSize(hFile: HMMIO): Boolean; publicdestructor Destroy; override;function Open(FileName: string): Boolean; //從文件打開function OpenResource(ResName: string): Boolean; //從資源打開, 資源的指定格式必須是 WAVEfunction OpenDialog: Boolean; //從對話框打開function Read(pDest: Pointer; Size: DWORD): Boolean; //讀出波形數據property Format: TWaveFormatEx read FFormat; //讀出格式數據property Size: DWORD read FSize; //讀出波形數據的大小 end;implementation{ TReadWave }destructor TReadWave.Destroy; beginif FFileHandle > 0 then mmioClose(FFileHandle, 0);inherited; end;function TReadWave.GetFormatAndSize(hFile: HMMIO): Boolean; varckiRIFF,ckiFmt,ckiData: TMMCKInfo; beginResult := False;if hFile = 0 then Exit;ZeroMemory(@ckiRIFF, SizeOf(TMMCKInfo));mmioDescend(hFile, @ckiRIFF, nil, MMIO_FINDRIFF);if (ckiRIFF.ckid <> FOURCC_RIFF) or (ckiRIFF.fccType <> mmioStringToFOURCC('WAVE',0)) then Exit;ZeroMemory(@FFormat, SizeOf(TWaveFormatEx));ZeroMemory(@ckiFmt, SizeOf(TMMCKInfo));ckiFmt.ckid := mmioStringToFOURCC('fmt', 0);ZeroMemory(@ckiData, SizeOf(TMMCKInfo));ckiData.ckid := mmioStringToFOURCC('data', 0);if (mmioDescend(hFile, @ckiFmt, @ckiRIFF, MMIO_FINDCHUNK) = MMSYSERR_NOERROR) then mmioRead(hFile, @FFormat, SizeOf(TWaveFormatEx));mmioAscend(hFile, @ckiFmt, 0);if (mmioDescend(hFile, @ckiData, @ckiRIFF, MMIO_FINDCHUNK) = MMSYSERR_NOERROR) then FSize := ckiData.cksize;Result := FFormat.wFormatTag = WAVE_FORMAT_PCM; end;function TReadWave.Open(FileName: string): Boolean; beginResult := False;if not FileExists(FileName) then Exit;if FFileHandle > 0 then mmioClose(FFileHandle, 0);FFileHandle := mmioOpen(PChar(FileName), nil, MMIO_READ);Result := GetFormatAndSize(FFileHandle); end;function TReadWave.OpenDialog: Boolean; beginwith TOpenDialog.Create(nil) do beginFilter := 'Wave File(*.wav)|*.wav';if Execute then Result := Open(FileName);Free;end; end;function TReadWave.OpenResource(ResName: string): Boolean; varres: TResourceStream;mmioInfo: TMMIOInfo; beginResult := False;res := TResourceStream.Create(HInstance, ResName, 'WAVE');ZeroMemory(@mmioInfo, SizeOf(TMMIOInfo));mmioInfo.fccIOProc := FOURCC_MEM;mmioInfo.cchBuffer := res.Size;mmioInfo.pchBuffer := res.Memory;if FFileHandle > 0 then mmioClose(FFileHandle, 0);FFileHandle := mmioOpen(nil, @mmioInfo, MMIO_ALLOCBUF or MMIO_READ);Result := GetFormatAndSize(FFileHandle);res.Free; end;function TReadWave.Read(pDest: Pointer; Size: DWORD): Boolean; beginResult := mmioRead(FFileHandle, pDest, Size) = Size; end;end.
測試代碼:
unit Unit1;interfaceusesWindows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,Dialogs, StdCtrls, ExtCtrls, ComCtrls;typeTForm1 = class(TForm)Button1: TButton; //打開并播放Button2: TButton; //停止TrackBar1: TTrackBar; //用于調整 TDSFXGargle.dwRateHzRadioGroup1: TRadioGroup; //用于調整 TDSFXGargle.dwWaveShapeprocedure FormCreate(Sender: TObject);procedure FormDestroy(Sender: TObject);procedure Button1Click(Sender: TObject);procedure Button2Click(Sender: TObject);procedure TrackBar1Change(Sender: TObject); //RadioGroup1.OnClick 也關聯它end;varForm1: TForm1;implementation{$R *.dfm}uses DirectSound, ReadWave2; //ReadWave2 是剛剛修改過的自定義單元varmyDSound: IDirectSound8;buf8: IDirectSoundBuffer8;fxGargle: IDirectSoundFXGargle8; //IDirectSoundFXGargle8 效果器{建立設備對象并初始化界面} procedure TForm1.FormCreate(Sender: TObject); beginDirectSoundCreate8(nil, myDSound, nil);myDSound.SetCooperativeLevel(Handle, DSSCL_NORMAL);TrackBar1.Min := DSFXGARGLE_RATEHZ_MIN; //1TrackBar1.Max := DSFXGARGLE_RATEHZ_MAX; //1000TrackBar1.Position := 20; //默認值TrackBar1.ShowSelRange := False;TrackBar1.TickStyle := tsNone;RadioGroup1.Items.CommaText := 'TRIANGLE, SQUARE';RadioGroup1.Columns := 2;RadioGroup1.ItemIndex := 0;RadioGroup1.OnClick := TrackBar1.OnChange; //兩個事件的代碼相同System.ReportMemoryLeaksOnShutdown := true; end;{建立緩沖區、關聯特效、獲取特效對象并播放} procedure TForm1.Button1Click(Sender: TObject); varbuf: IDirectSoundBuffer; //最終需要的是 IDirectSoundBuffer8, 這里的 IDirectSoundBuffer 只是做個橋bufDesc: TDSBufferDesc;rEffect: TDSEffectDesc; //SetFX() 方法需要的結構wav: TReadWave;p1: Pointer;n1: DWORD; begin{經過對自定義單元的修改, 現在調入一個 Wave 很方便}wav := TReadWave.Create;if not wav.OpenDialog then begin wav.Free; Exit; end;{獲取 IDirectSoundBuffer8 接口對象}ZeroMemory(@bufDesc, SizeOf(TDSBufferDesc));bufDesc.dwSize := SizeOf(TDSBufferDesc);bufDesc.dwFlags := DSBCAPS_CTRLFX; //!bufDesc.dwBufferBytes := wav.Size;bufDesc.lpwfxFormat := @wav.Format;myDSound.CreateSoundBuffer(bufDesc, buf, nil);buf.QueryInterface(IID_IDirectSoundBuffer8, buf8);{載入波形}buf8.Lock(0, 0, @p1, @n1, nil, nil, DSBLOCK_ENTIREBUFFER);wav.Read(p1, n1);wav.Free;buf8.Unlock(p1, n1, nil, 0);{準備 SetFX() 需要的結構}ZeroMemory(@rEffect, SizeOf(TDSEffectDesc));rEffect.dwSize := SizeOf(TDSEffectDesc);rEffect.dwFlags := 0;rEffect.guidDSFXClass := GUID_DSFX_STANDARD_GARGLE; //指定是 IDirectSoundFXGargle8 效果器{關聯效果器}buf8.SetFX(1, @rEffect, nil); //參數應該是個數組, 既然只有一個元素, 就先省了{獲取效果器對象}buf8.GetObjectInPath(GUID_DSFX_STANDARD_GARGLE, 0, IID_IDirectSoundFXGargle8, fxGargle);{播放}buf8.Play(0, 0, DSBPLAY_LOOPING);// buf := nil; //局部接口會被自動釋放 end;{停止播放} procedure TForm1.Button2Click(Sender: TObject); beginif Assigned(buf8) then buf8.Stop; end;{特效變換} procedure TForm1.TrackBar1Change(Sender: TObject); varrGargle: TDSFXGargle; beginif buf8 = nil then Exit;rGargle.dwRateHz := TrackBar1.Position;rGargle.dwWaveShape := RadioGroup1.ItemIndex;fxGargle.SetAllParameters(rGargle); end;procedure TForm1.FormDestroy(Sender: TObject); beginbuf8 := nil;myDSound := nil; end;end.
運行效果圖:
轉載于:https://www.cnblogs.com/del/archive/2011/01/21/1941193.html
總結
以上是生活随笔為你收集整理的在 Delphi 下使用 DirectSound (9): 效果器初步及 IDirectSoundFXGargle8 效果器的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 在 Delphi 下使用 DirectS
- 下一篇: jquery键盘事件