使用 NAudio c# 将 wma 音频流转换为 mp3 流

2024-05-20

我的任务是使用 NAudio 和 Lame 将 wma 音频流转换为 mp3 流。下面的代码可以很好地处理文件名,但我希望它可以使用内存流来完成。我在 NAudio 中搜索没有读取 wma 音频流的方法。 NAudio 可以吗?

    public static byte[] ConvertWmaToMp3(uint bitrate = 128)
    {

        FileStream fs = new FileStream("..\\sample.wma", FileMode.Open, FileAccess.Read);            
        var ws = new NAudio.WindowsMediaFormat.WMAFileReader(fs.Name);                                    

        // Setup encoder configuration
        WaveLib.WaveFormat fmt = new WaveLib.WaveFormat(ws.WaveFormat.SampleRate, 16, ws.WaveFormat.Channels);
        Yeti.Lame.BE_CONFIG beconf = new Yeti.Lame.BE_CONFIG(fmt, bitrate);

        // Encode WAV to MP3
        int blen = ws.WaveFormat.AverageBytesPerSecond;
        byte[] buffer = new byte[blen];
        byte[] mp3data = null;

        using (MemoryStream mp3strm = new MemoryStream())
        using (Mp3Writer mp3wri = new Mp3Writer(mp3strm, fmt, beconf))
        {
            int rc;
            while ((rc = ws.Read(buffer, 0, blen)) > 0)
            {
                mp3wri.Write(buffer, 0, rc);
            }

            mp3data = mp3strm.ToArray();
        }

        return mp3data;                      

    }

目前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 支持它。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 NAudio c# 将 wma 音频流转换为 mp3 流 的相关文章

随机推荐

  • 无法在 osx-arm64 上安装 Python 3.7

    我正在尝试使用 Conda 创建一个带有 Python 3 7 的新环境 例如 conda create n qnn python 3 7 我收到以下错误 Collecting package metadata current repoda
  • \add_34/U1_1_6 的 Verilog 命名约定

    有人可以解释一下这个命名约定在下面的 Verilog 行中意味着什么吗 我不知道这是什么 add 34 部分的意思是 ADDHXL add 34 U1 1 6 A n1022 B add 34 carry 6 CO add 34 carry
  • 折叠具有多个字段的行

    我有这个代码 awk seen 1 2 a 1 a 1 a 1 t 2 END for i in a print i a i inputfile 我想折叠具有两个以上字段的行 但始终基于第一个字段作为索引 输入文件 三列制表符分隔 prot
  • 逃离的正确方法是什么?使用 Oracle 12c MATCH_RECOGNIZE 时 JDBCPreparedStatement 中的字符?

    以下查询在 Oracle 12c 中是正确的 SELECT FROM dual MATCH RECOGNIZE MEASURES a dummy AS dummy PATTERN a DEFINE a AS 1 1 但它不能通过 JDBC
  • ASP MVC:服务应该返回 IQueryable 的吗?

    你怎么认为 你的 DAO 应该返回一个 IQueryable 以便在你的控制器中使用它吗 不 您的控制器根本不应该处理任何复杂的逻辑 保持苗条身材 模型 而不是 DAO 应该将控制器返回给视图所需的所有内容 我认为在控制器类中看到查询 甚至
  • Typeahead.js substringMatcher 函数说明

    我只是在做一些研究Typeahead js这是一个非常酷的图书馆 感谢文档 我已经成功地获得了一个基本的示例 该文档也非常好 但是我试图弄清楚以下代码块实际上在做什么 var substringMatcher function strs r
  • IronPython:没有名为 json 的模块

    我安装了 IronPython 我的 python 文件如下所示 import sys print sys version import json 运行它的代码 var p Python CreateEngine var scope p C
  • python Soap zeep模块获取结果

    我从 SOAP API 得到如下结果 client zeep Client wsdl self wsdl transport transport auth header lb E authenticate self login res cl
  • WordPress 自定义帖子类型未显示在搜索结果中

    我在 WordPress 中遇到自定义帖子类型 测验 和搜索的问题 自定义帖子类型未显示在我的搜索结果页面中 我的搜索结果中仅显示默认的帖子内容 以下是我使用的代码 函数 php函数create posttype register post
  • 创建嵌套字典单行

    您好 我有三个列表 我想使用一行创建一个三级嵌套字典 i e l1 a b l2 1 2 3 l3 d e 我想创建以下嵌套字典 nd a 1 d 0 e 0 2 d 0 e 0 3 d 0 e 0 b a 1 d 0 e 0 2 d 0
  • 按下表格视图单元格时更改视图?

    我需要帮助 当我的 tableView 的单元格被选择时 我希望该单元格转到它自己的页面 我不希望每个单元格都转到同一页面 我尝试使用 FirstFolderViewController first FirstFolderViewContr
  • IE 中的 jQuery .width(val) 错误 - 无效参数

    通过ajax加载内部div book table 后 我想调整正文的宽度以适应更大的内容 var new width parseInt book table css width 407 body width new width 在 FF 和
  • 如何在 Perl 中使用原始套接字?

    你怎样才能得到一个rawPerl 中的套接字 那么构建与其一起使用的数据包的最佳方法是什么 与在 C 中执行的操作相同 通过在创建套接字时设置套接字类型 在示例中CPAN http search cpan org rgarcia perl
  • 在脚本内使用不带密码的 sudo

    由于某种原因 我需要作为用户在没有 sudo 的情况下运行脚本 script sh 该脚本需要 root 权限才能工作 我认为将 sudo 放入 script sh 中是唯一的解决方案 让我们举个例子 script sh bin sh su
  • 安装 2.15 后 ggplot2 中的 alpha 通道不起作用

    更新到 R 2 15 后 ggplot 中的 alpha 通道似乎不再起作用 plot rnorm 100 rnorm 100 bg cc000055 pch 21 工作得很好但是 qplot rnorm 100 rnorm 100 col
  • 使用函数的 SQL 查询 - 如何获取列表的最大计数

    如何查询 MAXIMUM COUNT 交易次数 我的代码如下 SELECT customer id COUNT customer id FROM rental GROUP BY customer id HAVING MAX COUNT cu
  • 将名称字符串编码为唯一的数字

    我有一大堆名字 数以百万计 他们每个人都有一个名字 一个可选的中间名和一个姓氏 我需要将这些名称编码为唯一代表这些名称的数字 编码应该是一对一的 即一个名称只能与一个数字相关联 一个数字只能与一个名称相关联 对此进行编码的明智方法是什么 我
  • 当前的 c++ 工作草案与当前标准有何不同

    通过搜索该标准的 PDF 版本 我最终找到了这个链接C 标准措辞草案 http www open std org jtc1 sc22 wg21 docs papers 2012 n3376 pdf从 2011 年开始 我意识到我可以购买最终
  • 如何识别 WPF 文本框中的 ValidationError 工具提示位置

    我添加了一个箭头来指示工具提示中的文本框 当文本框远离屏幕边缘时 这非常有效 但是当它靠近屏幕边缘时 工具提示位置发生变化 箭头显示在左侧 Here is the Image Correct as expected since TextBo
  • 使用 NAudio c# 将 wma 音频流转换为 mp3 流

    我的任务是使用 NAudio 和 Lame 将 wma 音频流转换为 mp3 流 下面的代码可以很好地处理文件名 但我希望它可以使用内存流来完成 我在 NAudio 中搜索没有读取 wma 音频流的方法 NAudio 可以吗 public