目前WMAFileReader
类不支持从流中读取数据。 WMA API 支持从 WMA 读取IStream
所以这绝对是可能的。
如果您想自己实现流式传输,则需要获取源代码WmaFileReader http://naudio.codeplex.com/SourceControl/latest#NAudio.WindowsMediaFormat/WmaFileReader.cs and WmaStream http://naudio.codeplex.com/SourceControl/latest#NAudio.WindowsMediaFormat/Interop/WmaStream.cs来自 CodePlex,并将它们用作修改后的类的模板。
您首先需要一个提供 COM 的包装类IStream
.NET 接口Stream
。这是一个简单的:
public class InteropStream : IStream, IDisposable
{
public readonly Stream intern;
public InteropStream(Stream strm)
{
intern = strm;
}
~InteropStream()
{
Dispose(true);
}
public void Dispose()
{
Dispose(false);
}
protected void Dispose(bool final)
{
if (final)
intern.Dispose();
}
#region IStream Members
public void Clone(out IStream ppstm)
{
ppstm = null;
}
public void Commit(int grfCommitFlags)
{
intern.Flush();
}
readonly byte[] buffer = new byte[4096];
public void CopyTo(IStream pstm, long cb, IntPtr pcbRead, IntPtr pcbWritten)
{
if (pcbRead != IntPtr.Zero)
Marshal.WriteInt32(pcbRead, 0);
if (pcbWritten != IntPtr.Zero)
Marshal.WriteInt32(pcbWritten, 0);
}
public void LockRegion(long libOffset, long cb, int dwLockType)
{ }
public void Read(byte[] pv, int cb, IntPtr pcbRead)
{
int rc = intern.Read(pv, 0, cb);
if (pcbRead != IntPtr.Zero)
Marshal.WriteInt32(pcbRead, rc);
}
public void Revert()
{ }
public void Seek(long dlibMove, int dwOrigin, IntPtr plibNewPosition)
{
long origin = 0;
if (dwOrigin == 1) // STREAM_SEEK_CUR
origin = intern.Position;
else if (dwOrigin == 2) // STREAM_SEEK_END
origin = intern.Length;
long pos = origin + dlibMove;
intern.Position = pos;
if (plibNewPosition != IntPtr.Zero)
Marshal.WriteInt64(plibNewPosition, pos);
}
public void SetSize(long libNewSize)
{ }
public void Stat(out System.Runtime.InteropServices.ComTypes.STATSTG pstatstg, int grfStatFlag)
{
var res = new System.Runtime.InteropServices.ComTypes.STATSTG();
res.type = 2; // STGTY_STREAM
res.cbSize = intern.Length;
pstatstg = res;
}
public void UnlockRegion(long libOffset, long cb, int dwLockType)
{ }
public void Write(byte[] pv, int cb, IntPtr pcbWritten)
{ }
#endregion
}
接下来复制WmaStream
将代码添加到项目中的新命名空间中,并将以下代码添加到类的顶部:
InteropStream interopStrm = null;
public WmaStream(Stream fileStream)
: this(fileStream, null)
{ }
public WmaStream(Stream fileStream, WaveFormat OutputFormat)
{
interopStrm = new InteropStream(fileStream);
m_reader = WM.CreateSyncReader(WMT_RIGHTS.WMT_RIGHT_NO_DRM);
try
{
IWMSyncReader2 rdr = m_reader as IWMSyncReader2;
rdr.OpenStream(interopStrm);
Init(OutputFormat);
}
catch
{
try
{
m_reader.Close();
}
catch
{
}
m_reader = null;
throw;
}
}
做同样的事情WmaFileReader
和以下代码:
public WMAFileReader(Stream wmaStream)
{
m_wmaStream = new WmaStream2(wmaStream);
m_waveFormat = m_wmaStream.Format;
}
现在您可以创建修改后的实例WmaFileReader
使用文件名或Stream
实例 -MemoryStream
, FileStream
等。Stream
实例需要可读且可查找。
我已经在我的计算机上找到的一些随机 WMA 文件尝试了上述方法,并将其加载到MemoryStream
或使用FileStream
,并且它按我的预期工作。
据推测,Mark 正在努力将此功能添加到 NAudio.Wma 包中,因此请将此视为临时修复,直到 NAudio 支持它。