如何使用DirectShow.NET C#访问音频流

我想要做的是将任意音频文件传递给DirectShowfilter图并最终使用.NET 3.5 C#和DirectShow.NET接收(PCM音频)流对象。 我想说的是我可以说:

Stream OpenFile(string filename) {...} 

 stream.Read(...) 

我已经阅读了DirectShow几天,并认为我已经开始掌握filter和filter图的想法。 我找到了如何播放音频或将其写入文件的示例( 文件 / 设备 ),但似乎无法找到Stream对象的解决方案。 这有可能吗? 如果我错过了什么,你能指出我正确的方向吗?

最好,

Hauke

我想与你分享我自己的问题的解决方案(我的重点是异国情调的bwf文件格式。因此名称。):

  using System; using System.Collections.Generic; using System.Text; using DirectShowLib; using System.Runtime.InteropServices; using System.IO; namespace ConvertBWF2WAV { public class BWF2WavConverter : ISampleGrabberCB { IFilterGraph2 gb = null; ICaptureGraphBuilder2 icgb = null; IBaseFilter ibfSrcFile = null; DsROTEntry m_rot = null; IMediaControl m_mediaCtrl = null; ISampleGrabber sg = null; public BWF2WavConverter() { // Initialize int hr; icgb = (ICaptureGraphBuilder2)new CaptureGraphBuilder2(); gb = (IFilterGraph2) new FilterGraph(); sg = (ISampleGrabber)new SampleGrabber(); #if DEBUG m_rot = new DsROTEntry(gb); #endif hr = icgb.SetFiltergraph(gb); DsError.ThrowExceptionForHR(hr); } public void reset() { gb = null; icgb = null; ibfSrcFile = null; m_rot = null; m_mediaCtrl = null; } public void convert(object obj) { string[] pair = obj as string[]; string srcfile = pair[0]; string targetfile = pair[1]; int hr; ibfSrcFile = (IBaseFilter)new AsyncReader(); hr = gb.AddFilter(ibfSrcFile, "Reader"); DsError.ThrowExceptionForHR(hr); IFileSourceFilter ifileSource = (IFileSourceFilter)ibfSrcFile; hr = ifileSource.Load(srcfile, null); DsError.ThrowExceptionForHR(hr); // the guid is the one from ffdshow Type fftype = Type.GetTypeFromCLSID(new Guid("0F40E1E5-4F79-4988-B1A9-CC98794E6B55")); object ffdshow = Activator.CreateInstance(fftype); hr = gb.AddFilter((IBaseFilter)ffdshow, "ffdshow"); DsError.ThrowExceptionForHR(hr); // the guid is the one from the WAV Dest sample in the SDK Type type = Type.GetTypeFromCLSID(new Guid("3C78B8E2-6C4D-11d1-ADE2-0000F8754B99")); object wavedest = Activator.CreateInstance(type); hr = gb.AddFilter((IBaseFilter)wavedest, "WAV Dest"); DsError.ThrowExceptionForHR(hr); // manually tell the graph builder to try to hook up the pin that is left IPin pWaveDestOut = null; hr = icgb.FindPin(wavedest, PinDirection.Output, null, null, true, 0, out pWaveDestOut); DsError.ThrowExceptionForHR(hr); // render step 1 hr = icgb.RenderStream(null, null, ibfSrcFile, (IBaseFilter)ffdshow, (IBaseFilter)wavedest); DsError.ThrowExceptionForHR(hr); // Configure the sample grabber IBaseFilter baseGrabFlt = sg as IBaseFilter; ConfigSampleGrabber(sg); IPin pGrabberIn = DsFindPin.ByDirection(baseGrabFlt, PinDirection.Input, 0); IPin pGrabberOut = DsFindPin.ByDirection(baseGrabFlt, PinDirection.Output, 0); hr = gb.AddFilter((IBaseFilter)sg, "SampleGrabber"); DsError.ThrowExceptionForHR(hr); AMMediaType mediatype = new AMMediaType(); sg.GetConnectedMediaType(mediatype); hr = gb.Connect(pWaveDestOut, pGrabberIn); DsError.ThrowExceptionForHR(hr); // file writer FileWriter file_writer = new FileWriter(); IFileSinkFilter fs = (IFileSinkFilter)file_writer; fs.SetFileName(targetfile, null); hr = gb.AddFilter((DirectShowLib.IBaseFilter)file_writer, "File Writer"); DsError.ThrowExceptionForHR(hr); // render step 2 AMMediaType mediatype2 = new AMMediaType(); pWaveDestOut.ConnectionMediaType(mediatype2); gb.Render(pGrabberOut); // alternatively to the file writer use the NullRenderer() to just discard the rest // assign control m_mediaCtrl = gb as IMediaControl; // run hr = m_mediaCtrl.Run(); DsError.ThrowExceptionForHR(hr); } // // configure the SampleGrabber filter of the graph // void ConfigSampleGrabber(ISampleGrabber sampGrabber) { AMMediaType media; // set the media type. works with "stream" somehow... media = new AMMediaType(); media.majorType = MediaType.Stream; //media.subType = MediaSubType.WAVE; //media.formatType = FormatType.WaveEx; // that's the call to the ISampleGrabber interface sg.SetMediaType(media); DsUtils.FreeAMMediaType(media); media = null; // set BufferCB as the desired Callback function sg.SetCallback(this, 1); } public int SampleCB(double a, IMediaSample b) { return 0; } ///  /// Called on each SampleGrabber hit. ///  /// Starting time of the sample, in seconds. /// Pointer to a buffer that contains the sample data. /// Length of the buffer pointed to by pBuffer, in bytes. ///  public int BufferCB(double SampleTime, IntPtr pBuffer, int BufferLen) { byte[] buffer = new byte[BufferLen]; Marshal.Copy(pBuffer, buffer, 0, BufferLen); using (BinaryWriter binWriter = new BinaryWriter(File.Open(@"C:\directshowoutput.pcm", FileMode.Append))) { binWriter.Write(buffer); } return 0; } } } 

这个( AVILibrary Wrapper )可能会引导你找到一个解决方案,它不是基于DirectSound的(我感觉非常偏向于将代码与回放硬件接口),但可能就是答案。

另一种方法可以在这里找到。