C# DirectSound DirectSoundBuffer.SetVolume E_NOINTERFACE
本文关键字:NOINTERFACE SetVolume DirectSound DirectSoundBuffer | 更新日期: 2023-09-27 18:37:21
我正在为我的音频库编写一个 DirectSound 包装器。我遇到了直接声音,效果很好。这意味着音频播放比波形等效果要好得多。但是现在我有一个问题。我正在尝试设置辅助缓冲区的音量。我收到一个例外,即存在 HResult E_NOINTERFACE,因为我的界面无法转换或类似的东西。这怎么可能。我有这个用于 SetVolume 方法的代码:void SetVolume(int lVolume);
例如,我正在向其传递 -56 的值。
这是确切的错误消息:
类型为"System.__ComObject"的 COM 对象不能强制转换为接口类型"AMEngine.DX.IDirectSoundBuffer"。无法执行此操作,因为无法执行 IID '{279AFA85-4981-11CE-A521-0020AF0BE560} 的接口的 COM 组件上的查询接口调用:不支持此类接口(HRESULT 的异常:0x80004002 (E_NOINTERFACE))。
我已经翻译了这个:
DEFINE_GUID(IID_IDirectSoundBuffer, 0x279AFA85, 0x4981, 0x11CE, 0xA5, 0x21, 0x00, 0x20, 0xAF, 0x0B, 0xE5, 0x60);
#undef INTERFACE
#define INTERFACE IDirectSoundBuffer
DECLARE_INTERFACE_(IDirectSoundBuffer, IUnknown)
{
STDMETHOD(QueryInterface) (THIS_ __in REFIID, __deref_out LPVOID*) PURE;
STDMETHOD_(ULONG,AddRef) (THIS) PURE;
STDMETHOD_(ULONG,Release) (THIS) PURE;
STDMETHOD(GetCaps) (THIS_ __out LPDSBCAPS pDSBufferCaps) PURE;
STDMETHOD(GetCurrentPosition) (THIS_ __out_opt LPDWORD pdwCurrentPlayCursor, __out_opt LPDWORD pdwCurrentWriteCursor) PURE;
STDMETHOD(GetFormat) (THIS_ __out_bcount_opt(dwSizeAllocated) LPWAVEFORMATEX pwfxFormat, DWORD dwSizeAllocated, __out_opt LPDWORD pdwSizeWritten) PURE;
STDMETHOD(GetVolume) (THIS_ __out LPLONG plVolume) PURE;
STDMETHOD(GetPan) (THIS_ __out LPLONG plPan) PURE;
STDMETHOD(GetFrequency) (THIS_ __out LPDWORD pdwFrequency) PURE;
STDMETHOD(GetStatus) (THIS_ __out LPDWORD pdwStatus) PURE;
STDMETHOD(Initialize) (THIS_ __in LPDIRECTSOUND pDirectSound, __in LPCDSBUFFERDESC pcDSBufferDesc) PURE;
STDMETHOD(Lock) (THIS_ DWORD dwOffset, DWORD dwBytes,
__deref_out_bcount(*pdwAudioBytes1) LPVOID *ppvAudioPtr1, __out LPDWORD pdwAudioBytes1,
__deref_opt_out_bcount(*pdwAudioBytes2) LPVOID *ppvAudioPtr2, __out_opt LPDWORD pdwAudioBytes2, DWORD dwFlags) PURE;
STDMETHOD(Play) (THIS_ DWORD dwReserved1, DWORD dwPriority, DWORD dwFlags) PURE;
STDMETHOD(SetCurrentPosition) (THIS_ DWORD dwNewPosition) PURE;
STDMETHOD(SetFormat) (THIS_ __in LPCWAVEFORMATEX pcfxFormat) PURE;
STDMETHOD(SetVolume) (THIS_ LONG lVolume) PURE;
STDMETHOD(SetPan) (THIS_ LONG lPan) PURE;
STDMETHOD(SetFrequency) (THIS_ DWORD dwFrequency) PURE;
STDMETHOD(Stop) (THIS) PURE;
STDMETHOD(Unlock) (THIS_ __in_bcount(dwAudioBytes1) LPVOID pvAudioPtr1, DWORD dwAudioBytes1,
__in_bcount_opt(dwAudioBytes2) LPVOID pvAudioPtr2, DWORD dwAudioBytes2) PURE;
STDMETHOD(Restore) (THIS) PURE;
};
到
/// <summary>
/// Line 687 Dsound.h
/// </summary>
[ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("279AFA85-4981-11CE-A521-0020AF0BE560")]
public interface IDirectSoundBuffer
{
//IDirectSoundBuffer methods
void GetCaps([Out, MarshalAs(UnmanagedType.LPStruct)] DSBufferCaps pDSBufferCaps); //TODO
void GetCurrentPosition([Out] out UInt32 pdwCurrentPlayCursor, [Out] out UInt32 pdwCurrentWriteCursor);
void GetFormat([Out, MarshalAs(UnmanagedType.CustomMarshaler, MarshalType = "AMEngine.Wave.WaveFormatMarshaler")] out AMEngine.Wave.WaveFormat pwfxFormat,
int dwSizeAllocated, [Out] out int pdwSizeWritten); //TODO implement
[return: MarshalAs(UnmanagedType.I4) /*See http://msdn.microsoft.com/en-us/library/aa288468%28v=vs.71%29.aspx */]
Int32 GetVolume();
[return: MarshalAs(UnmanagedType.I4)]
Int32 GetPan();
[return: MarshalAs(UnmanagedType.I4)]
Int32 GetFrequency();
[return: MarshalAs(UnmanagedType.I4)]
Int32 GetStatus();
void Initialize([In, MarshalAs(UnmanagedType.Interface)] IDirectSound pDirectSound, [In] DSBufferDescription pcDSBufferDesc);
void Lock(int dwOffset, int dwBytes,
[Out] out IntPtr ppvAudioPtr1, [Out] out int pdwAudioBytes1,
[Out] out IntPtr ppvAudioPtr2, [Out] out int pdwAudioBytes2,
DSBLock dwFlags /*TODO Flags enum erstellen */);
void Play(int dwReserved1, int dwPriority, DSBPlayFlags dwFlags); //TODO Flags enum erstellen -- Done
void SetCurrentPosition(int dwNewPosition);
void SetFormat([In] AMEngine.Wave.WaveFormat pcfxFormat);
void SetVolume(int lVolume);
void SetPan(int lPan);
void SetFrequency(int dwFrequency);
void Stop();
void Unlock([In] IntPtr pvAudioPtr1, int dwAudioBytes1,
[In] IntPtr pvAudioPtr2, int dwAudioBytes2);
void Restore();
}
使用以下代码成功创建它:
DSBufferDescription secondaryBufferDesc = new DSBufferDescription();
secondaryBufferDesc.dwBufferBytes = (uint)(bufferSize * 2);
//http://msdn.microsoft.com/en-us/library/windows/desktop/microsoft.directx_sdk.reference.dsbcaps%28v=vs.85%29.aspx
secondaryBufferDesc.dwFlags = DirectSoundBufferCaps.DSBCAPS_CTRLVOLUME |
DirectSoundBufferCaps.DSBCAPS_CTRLPOSITIONNOTIFY |
DirectSoundBufferCaps.DSBCAPS_GETCURRENTPOSITION2 |
DirectSoundBufferCaps.DSBCAPS_GLOBALFOCUS |
DirectSoundBufferCaps.DSBCAPS_STICKYFOCUS;
secondaryBufferDesc.dwReserved = 0;
secondaryBufferDesc.dwSize = Marshal.SizeOf(secondaryBufferDesc);
secondaryBufferDesc.guid3DAlgorithm = Guid.Empty;
secondaryBufferDesc.guid3DAlgorithm = Guid.Empty;
Wave.WaveFormat format = new Wave.WaveFormat(waveFormat, waveFormat.SampleRate);
GCHandle lpwfxSecondaryPtr = GCHandle.Alloc(format, GCHandleType.Pinned);
secondaryBufferDesc.lpwfxFormat = lpwfxSecondaryPtr.AddrOfPinnedObject();
//IntPtr waveFormatPtr = Marshal.AllocHGlobal(Marshal.SizeOf(waveFormat));
//Marshal.StructureToPtr(waveFormat, waveFormatPtr, false);
//secondaryBufferDesc.lpwfxFormat = waveFormatPtr;
object primaryBufferObj, secondaryBufferObj;
//http://msdn.microsoft.com/en-us/library/windows/desktop/microsoft.directx_sdk.idirectsound8.idirectsound8.createsoundbuffer%28v=vs.85%29.aspx
directSound.CreateSoundBuffer(primaryBufferDesc, out primaryBufferObj, IntPtr.Zero);
directSound.CreateSoundBuffer(secondaryBufferDesc, out secondaryBufferObj, IntPtr.Zero);
lpwfxSecondaryPtr.Free();
this.primaryBuffer = (IDirectSoundBuffer)primaryBufferObj;
this.secondaryBuffer = (IDirectSoundBuffer)secondaryBufferObj;
音量使用以下代码设置:(我传递的值是 -56)无声音 = 0 和最大声音 = -10000
private void SetCurrentVolume()
{
if (secondaryBuffer != null)
{
secondaryBuffer.SetVolume(volume);
}
}
E_NOINTERFACE
错误很简单:用于查询另一个接口的接口指针无法为您提供该指针。也就是说,您(或者可能正在使用的库)正在从不是缓冲区对象的东西中 QI'ing IDirectSoundBuffer
。如果您在错误位置周围发布代码片段会很有帮助。