☰
NAudio 音频重采样完全指南:四种内置方案与源码级原理剖析
2026/10/10 8:49:31 网站建设 项目流程
  • 音视频
  • 音频处理

【免费下载链接】NAudio

Audio and MIDI library for .NET

项目地址:https://gitcode.com/gh_mirrors/na/NAudio
点击查看免费下载

重采样(Resampling)是音频处理中最常见的需求之一:混音前要把不同采样率的文件统一,ASIO 等设备输出前要把数据转换到设备当前的采样率。本文以 NAudio 仓库中的 Docs/Resampling.md 为骨架,系统讲解 NAudio 提供的四种重采样方案(Windows 的 Media Foundation、macOS 的 AudioConverter、跨平台的 WDL、遗留的 ACM),逐一给出可直接复制的代码示例、参数取值范围与质量档位说明,并结合仓库源码(MediaFoundationResampler.cs、MacAudioConverter.cs、WdlResamplingSampleProvider.cs 等)解释每种方案的底层工作原理、适用平台与限制。读完本文,你将能够在混音、设备播放、文件转码等场景中准确选择并正确使用 NAudio 的重采样器。

什么时候需要重采样

在 NAudio 中,几乎所有下游处理环节都对 WaveFormat(采样率、位深度、声道数)有严格要求,因此重采样通常出现在以下两类场景:

  • 混音前的统一采样率:将两个采样率不同的文件(例如一个 44.1kHz、一个 48kHz)混合到一起,必须先通过重采样让它们处于同一采样率,否则混音结果会出现音高与节奏错位。
  • 设备输出前的格式匹配:通过 ASIO 这类 API 播放时,数据必须以设备当前的采样率送入设备。若源文件采样率与设备不匹配,就必须先重采样。

需要注意的是,重采样并非简单的"插值补点",它暗藏一个经典陷阱——混叠(Aliasing)。

重采样前必须了解:混叠(Aliasing)问题

根据奈奎斯特定理,某采样率能正确表示的频率上限为采样率的一半。当降低采样率时,源音频中高于目标采样率一半的高频成分无法被正确表示,它们不会消失,而是会"折叠"回可听频段,形成失真,这就是混叠。

文档给出的核心结论是:

如果降低采样率,应当先使用低通滤波器滤除在低采样率下无法正确表示的高频,然后再做重采样。

好消息是:NAudio 提供的几个官方重采样器(Media Foundation、AudioConverter、WDL)内部都内置了高质量的滤波/抗混叠处理,因此日常使用时你通常无需手动挂低通滤波器;但如果你选择"自己动手"写重采样算法,就必须自行处理低通滤波,否则几乎必然产生明显的混叠。

Option 1:MediaFoundationResampler(Windows)

这是 NAudio 中功能最强大的重采样器,包装了 Windows 自带的 Media Foundation 重采样 MFT(CLSID_CResamplerMediaObject,GUID 为f447b69e-1884-4a7e-8055-346f74d6edb3,见 MediaFoundationResampler.cs),在 Windows 10 及之后所有受支持的 Windows 版本上均可使用。

能力与特点

  • 可调质量:ResamplerQuality取值 1~60,60 为最高质量,1 为线性插值;默认已是 60。它对应底层 MFT 的IWMResamplerProps.SetHalfFilterLength,即半滤波器长度(见 MediaFoundationResampler.cs)。
  • 足够快:官方文档说明其速度足以在最高质量档位下实时运行。
  • 灵活:可以在重采样同时改变声道数与位深度(仅限 PCM 与 IEEE float 输入/输出,源码中IsPcmOrIeeeFloat会校验这一点并抛出ArgumentException,见 MediaFoundationResampler.cs)。
  • 输入输出约束:构造函数要求输入输出均为 PCM 或 IEEE float;若传入非此类格式会立即抛异常,同时会在构造时探测 COM 对象,若系统缺少重采样 DLL 会快速失败(fail fast),而不是等到第一次 Read 才报错(见 MediaFoundationResampler.cs)。

使用示例:MP3(44.1kHz)重采样到 16kHz

using NAudio.Wave; int outRate = 16000; var inFile = @"test.mp3"; var outFile = @"test resampled MF.wav"; using var reader = new MediaFoundationReader(inFile); var outFormat = new WaveFormat(outRate, reader.WaveFormat.Channels); using var resampler = new MediaFoundationResampler(reader, outFormat); // resampler.ResamplerQuality = 60; // default 已经是 60(最高质量) WaveFileWriter.CreateWaveFile(outFile, resampler);

要点说明:

  • 它接受IWaveProvider作为输入,输出格式由传入的WaveFormat决定。示例中outFormat保持源文件的声道数,只改采样率。
  • 构造器还有一个便捷重载MediaFoundationResampler(sourceProvider, outputSampleRate),只指定目标采样率,会按源格式自动构造输出 WaveFormat(PCM 保持位深度、IEEE float 输出 float 格式,见 MediaFoundationResampler.cs)。
  • 若同时想改变位深度或声道数,把outFormat改成对应的WaveFormat(sampleRate, bitsPerSample, channels)即可,例如输出 16kHz/16bit/单声道。
  • 需要在重采样开始前设置ResamplerQuality,其 setter 会对 1~60 范围做校验(见 MediaFoundationResampler.cs)。

Option 2:MacAudioConverter(macOS)

macOS 的 wrappers 包(NAudio.MacOS)中提供了与MediaFoundationResampler同等强大的平台级重采样器MacAudioConverter,它包装了 macOS Audio Toolbox 的 AudioConverter。文档明确提示该包目前仅以预发布(pre-release)形式提供,安装时需要--prerelease参数:

dotnet add package NAudio.MacOS --prerelease

前提:此方案必须运行在 macOS 上(源码以[SupportedOSPlatform("ios2.0")]与[SupportedOSPlatform("macos10.2")]标注,见 MacAudioConverter.cs)。

能力与特点

  • 质量与 Windows Media 重采样器相当,并且更灵活:可以显式选择重采样算法、质量档位与抖动(dithering)算法。
  • 唯一的限制:不能在重采样过程中随时更改输入流的任何格式属性(这是与MediaFoundationResampler的主要差异,见 MacAudioConverter.cs)。
  • 通道映射:支持把输入声道映射到不同输出声道,甚至用-1禁用某些输入声道。
  • 格式约束:与 Windows 版本一致,只接受 PCM 与 IEEE float 格式(VerifyFormatIsIeeeFloatOrPCM校验,见 MacAudioConverter.cs)。

核心可配置项(源码枚举)

属性可选值说明
QualityAudioConverterQuality.Min(0)、Low(0x20)、Medium(0x40)、High(0x60)、Max(0x7F)默认 Normal;质量档位见 AudioConverterQuality.cs
ComplexityLinear(线性插值,最低质量最便宜)、Normal(默认)、Mastering(更高品质,更昂贵)、MinimumPhase(最小相位脉冲响应,具体噪底随质量档位变化,Low≈-96dB、Medium≈-144dB、High≈-160dB 且内部使用双精度)重采样算法,见 AudioConverterSampleRateComplexity.cs
DitheringNone(默认)、TPDF(三角概率密度白噪声抖动)、NoiseShaping(感知加权噪声整形抖动)仅 macOS 支持,见 AudioConverterDitheringAlgorithm.cs
DitheringBitLengthuint对指定位长度应用预设抖动算法,仅 macOS 支持

Complexity与Quality的交互值得注意:文档强调"重采样质量还取决于你使用的重采样算法",例如MinimumPhase模式下同样的Low/Medium/High档位对应不同的噪声底水平,且MinimumPhase High比Mastering Low快数倍。另外Linear模式下InitialPhase与PrimeMethod属性不生效。

SetChannelMap(int[] channelMap)用于自定义声道映射:数组长度必须等于输出声道数,每个元素是源格式的声道索引,-1表示该输出声道不使用任何输入声道。源码注释中给出的示例是"立体声输入复制到四声道输出的后两个声道":

int[] chMap = [ 0, 1, 0, 1 ]; theConverter.SetChannelMap(chMap);

另外,MacAudioConverter构造器内置了一个贴心处理:当源为单声道、目标为多声道时,默认的 AudioConverter 行为是只把单声道数据送到第一个声道、其余声道静音,因此源码会自动把通道映射表填为全 0,让单声道信号铺满所有输出声道(见 MacAudioConverter.cs)。如果遇到源端数据流不连续(discontinuity),可调用Reset()重置转换器内部缓冲状态。

使用示例:MP3 重采样到 16kHz

using NAudio.Wave; using NAudio.MacOS.AudioToolbox; int outRate = 16000; var inFile = @"test.mp3"; var outFile = @"test resampled AudioConverter.wav"; using var reader = ExtendedAudioFileReaderFromURL.CreateFromFile(inFile); var outFormat = new WaveFormat(outRate, reader.WaveFormat.Channels); using var resampler = new MacAudioConverter(reader, outFormat); // 默认是 Normal,Min 是最低,Max 是最高。 // 重采样质量同时也取决于所使用的重采样算法。 // resampler.Quality = AudioConverterQuality.Max; WaveFileWriter.CreateWaveFile(outFile, resampler);

要点说明:

  • 输入读取使用 macOS 包的ExtendedAudioFileReaderFromURL(继承自ExtendedAudioFileServicesReader,见 ExtendedAudioFileReaderFromURL.cs),而非 Windows 专用的MediaFoundationReader。
  • 如需更高质量,可组合设置,例如:
    resampler.Quality = AudioConverterQuality.Max; resampler.Complexity = AudioConverterSampleRateComplexityConstants.Mastering;
  • Read方法要求缓冲长度不小于目标格式的块对齐(BlockAlign),否则抛出ArgumentException(见 MacAudioConverter.cs)。

Option 3:WdlResamplingSampleProvider(跨平台)

第三种方案基于Cockos WDL resampler(NAudio 获得了作者 Justin Frankel 的许可使用)。它工作在浮点样本域,因此输入需要ISampleProvider。这是唯一一个完全托管(fully managed)代码实现的重采样器,可在没有 Media Foundation 的任何跨平台环境(Linux、macOS、移动端等)中使用。

底层原理(源码级)

  • 核心算法位于 WdlResampler.cs,由 C++ 版 WDL resampler 移植为 C#,默认使用float作为样本类型与 sinc 滤波器系数类型。
  • 包装类 WdlResamplingSampleProvider.cs 构造时:保留源声道数,目标格式固定为WaveFormat.CreateIeeeFloatWaveFormat(newSampleRate, channels);随后配置 WDL 引擎——SetMode(true, 2, false)开启插值并使用 2 个滤波器、SetFilterParms()采用默认滤波参数(filterpos 0.693、filterq 0.707)、SetFeedMode(false)设为输出驱动(pull 模式)、最后SetRates(sourceRate, newSampleRate)设定源/目标采样率(见 WdlResamplingSampleProvider.cs)。
  • 读取时按"输出帧数 → ResamplePrepare 计算需要的输入帧数 → 从源读取 → ResampleOut 生成输出"的流程驱动,天然适合链式 SampleProvider 管道(见 WdlResamplingSampleProvider.cs)。

使用示例:MP3 重采样到 16kHz 并写出 16bit WAV

int outRate = 16000; var inFile = @"test.mp3"; var outFile = @"test resampled WDL.wav"; using (var reader = new AudioFileReader(inFile)) { var resampler = new WdlResamplingSampleProvider(reader, outRate); WaveFileWriter.CreateWaveFile16(outFile, resampler); }

要点说明:

  • AudioFileReader负责把任意格式解码为浮点,正好满足ISampleProvider要求。
  • WaveFileWriter.CreateWaveFile16会在写文件时把浮点样本转换为 16bit,因此无需额外处理位深度。
  • 与媒体框架方案不同,WDL 方案没有Quality之类的公开设置;WdlResamplingSampleProvider固定采用 2 滤波器 + 插值的默认配置(更底层的WdlResampler.SetMode/SetFilterParms均带可选参数,供进阶用户直接操作 Dsp 层)。

优点与不足

  • 优点:纯托管、跨平台,逻辑上只需引入 NAudio.Core 即可,不依赖操作系统组件。
  • 不足:性能不一定比MediaFoundationResampler(或 macOS 的MacAudioConverter)更快。在追求极致吞吐的 Windows 实时场景,优先考虑平台原生方案。

Option 4:ACM 重采样器(Windows,遗留方案)

WaveFormatConversionStream是 NAudio 从早期版本就提供的 ACM(Audio Compression Manager) 重采样器,属于遗留方案;文档明确建议新代码优先使用MediaFoundationResampler或WdlResamplingSampleProvider。

限制

  • 只能重采样16bit 音频;
  • 不能同时改变声道数;
  • 输入必须是WaveStream(不是IWaveProvider)。

其实现是"把 WaveStream 包装成走 ACM Codec 的WaveFormatConversionProvider",并基于源/目标格式的AverageBytesPerSecond估算转换后长度与位置映射(见 WaveFormatConversionStream.cs)。正因如此,它的长度/位置只是估算值,不适合需要精确 seek 的场景。

使用示例:MP3 重采样到 16kHz

int outRate = 16000; var inFile = @"test.mp3"; var outFile = @"test resampled ACM.wav"; using (var reader = new Mp3FileReader(inFile)) { var outFormat = new WaveFormat(outRate, reader.WaveFormat.Channels); using (var resampler = new WaveFormatConversionStream(outFormat, reader)) { WaveFileWriter.CreateWaveFile(outFile, resampler); } }

该方案位于NAudio.WinMM程序集中(WaveFormatConversionStream.cs),仅适用于 Windows。同一程序集中还有WaveFormatConversionProvider可直接处理IWaveProvider,但同样的 16bit、不可改声道数限制依然适用。

Option 5:自己动手实现重采样

由于 NAudio 让开发者直接访问原始样本(ISampleProvider.Read(Span<float>)、IWaveProvider.Read(Span<byte>)),你完全可以自行编写重采样算法,例如线性插值或更复杂的多项式插值。

但文档给出了明确的警告:

如果不同时编写低通滤波器,你几乎必然会遇到严重的混叠问题。既然 NAudio 已经内置了 WDL 重采样器,所有需要托管重采样器的场景都应该直接使用它。

换句话说,自己实现通常只在教学、实验或对算法有特殊定制需求时才有意义;生产代码应优先复用官方方案。

方案选择速查

方案平台输入类型质量是否可同时改声道/位深状态
MediaFoundationResamplerWindows 10+IWaveProvider(PCM/IEEE float)1~60 可调,默认 60是推荐
MacAudioConvertermacOS(iOS 部分功能受限)IWaveProvider(PCM/IEEE float)Min/Max等五档 + 算法/抖动可选是(含通道映射)推荐(需--prerelease安装)
WdlResamplingSampleProvider跨平台(纯托管)ISampleProvider(浮点)固定默认配置,品质良好否(仅采样率)推荐(跨平台首选)
WaveFormatConversionStream(ACM)WindowsWaveStream依赖 ACM codec否(仅采样率,限 16bit)遗留,仅旧代码

选型建议一句话总结:Windows 实时/高性能场景用MediaFoundationResampler,macOS 场景用MacAudioConverter,需要跨平台或纯托管的场景用WdlResamplingSampleProvider,ACM 留给历史代码维护。

延伸阅读

  • 重采样的典型实战场景:MixTwoAudioFilesToWav.md(混音前统一采样率)、Resampling.md(本文档原文)
  • 输出设备采样率匹配相关:AsioPlayback.md、OutputDeviceTypes.md
  • 相关实现源码:MediaFoundationResampler.cs、MacAudioConverter.cs、WdlResamplingSampleProvider.cs、WdlResampler.cs、WaveFormatConversionStream.cs
  • 测试与示例:可在 NAudio.Windows.Tests 与 NAudio.Core.Tests 中检索重采样相关用例,结合真实项目验证各方案行为。
  • 音视频
  • 音频处理

【免费下载链接】NAudio

Audio and MIDI library for .NET

项目地址:https://gitcode.com/gh_mirrors/na/NAudio
点击查看免费下载
上一篇:Midway info 组件:应用信息查看与安全管控实战指南
下一篇:3分钟学会使用ncmdumpGUI:免费转换网易云音乐NCM文件的完整指南

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询