Windows Media Audio Professional 编码解码器功能
Windows Media Audio Professional 编码解码器功能发布日期: 12/9/2004 | 更新日期: 12/9/2004
Nick Vicars-Harris Microsoft Corporation 适用于: Microsoft® Windows Media® Format SDK Microsoft Windows Media Encoder 9 Series 摘要: 本文解释了 Windows Media Audio Professional 编码解码器如何在必要时将多声道音频内容转换为立体声音频内容。本文还演示了如何创建编码应用程序,从而使得内容作者能够确定如何进行这种转换。 ![]() 本页内容简介Microsoft® Windows Media® Audio Professional 编码解码器支持高分辨率多声道内容、从多声道到立体声的作者控制缩混,以及动态范围控制。利用本文提供的信息,编程人员可以使用 Windows Media Format 软件开发工具包 (SDK) 创建利用这些功能的编码或呈现应用程序。 多声道播放需要使用 Windows® XP 操作系统。该编码解码器的一个重要功能是在早期版本的 Windows 操作系统上或者在不支持多声道播放的系统配置(例如,只有两个扬声器的系统)上,将多声道缩混为立体声的功能。 本文将详细讲述多声道缩混算法,并说明动态范围控制的运行方式。 本文包括以下主题:
缩混为立体声Windows Media Audio Professional 编码解码器支持多声道编码和解码。如果播放系统支持多声道播放,对于应用程序开发人员来说则无需进一步的操作。多声道播放需要在 Windows XP 操作系统上使用 Windows Media Player 9 Series 或更高版本。如果播放系统不支持多声道播放,则解码过程必须将多声道内容转换为立体声输出。 缩混 指的是获取一定数量的音频内容声道,然后将其重新组织为更少声道结构的过程。本文所讨论的缩混是从六个声道缩混为两个声道。本文讨论的这个六声道音频配置包括两个右声道扬声器、两个左声道扬声器、一个中间声道扬声器,还有一个超低音扬声器。此配置称为 5.1 音频,这是因为有 5 个标准扬声器和一个超低音扬声器。 在下列情况下,需要进行缩混过程:
缩混过程开始时首先要输入三个值,称为缩混系数。这些值在公式中使用,用来从六个输入声道的每个声道计算出信号级别,然后将这些信号级别进行组合,从而生成两个输出声道。 编码应用程序负责提供一个用户界面,以便内容作者能够指定缩混系数。然后,该应用程序会使用这些系数计算出各个不同的信号级别。最后,该应用程序会向编码文件中插入一个元数据属性。该元数据属性的值是一个以逗号分隔的字符串,其中包含了上述信号级别。 在解码过程中,Windows Media Audio Professional 编码解码器会判断是否需要进行缩混。如果需要进行缩混,它将从编码文件的元数据标头中检索这些信号级别值,并执行缩混。 矩阵缩混 如果播放系统使用下列配置,Windows Media Audio Professional 编码解码器将使用一种特殊的缩混模式:
在此配置中,会以一种“矩阵解码器”可以解释的方式,将双声道缩混信号混合到两个物理声道中。如果音频卡要将其输出发送到一个带有“矩阵解码器”的用户音频/视频接收器,该接收器将能够将输入信号重新解码为四个声道(左、右、中间和环绕),以便获得环绕音响体验。 这种模式不会使用内容作者可能已经提供的任何缩混元数据。 这种模式不能用于缩混 7.1 声道内容。包括 7.1 声道音频的内容总是缩混为立体声。 作者控制的缩混 要改变缩混行为,内容作者最多可以提供三个缩混系数。编码应用程序应该提供一个用户界面,以便作者能够输入这些值,如在 Windows Media Encoder 中。然后,该应用程序使用 Windows Media Format SDK 提供的接口,将缩混信息写入文件。 下表对这三个缩混系数进行了说明。
该应用程序必须强制实施下表中所说明的限制。
缩混算法 要实现作者控制的缩混,编码应用程序必须在编码文件中插入 g_wszFold6To2Channels3 元数据属性。该属性的值是一个逗号分隔的字符串,其中包含了 Windows Media Audio Professional 编码解码器用于从多声道输入派生立体声输出的数字。本节将演示如何从内容作者指定的系数得出这些数字。 下列等式提供了 5.1 到 2.0 缩混的常用形式: LResult = B * (L + (LinearSurroundMix * LS) + (LinearCenterMix * C) + (LinearLFEMix * LFE)) RResult = B * (R + (LinearSurroundMix * RS) + (LinearCenterMix * C) + (LinearLFEMix * LFE)) LResult 和 RResult 为两个输出声道。L、R、LS、RS、C 和 LFE 为六个输入声道。 每个公式中的三个项目都使用线性系数进行了加权,这些线性系数是从内容作者提供的相对应缩混系数计算而来的。B 为从这些线性系数计算而来的比例系数。该比例系数是必需的,有了该比例系数,整个混合才永远不会得出大于 1 的得数。 下面的这些等式用于计算线性系数: LinearSurroundMix = 10 ^ (SurroundMix / 20) LinearCenterMix = 10 ^ (CenterMix / 20) LinearLFEMix = 10 ^ (LFEMix / 20) 此公式用于计算 B: B = 1 / (1 + LinearSurroundMix + LinearCenterMix + LinearLFEMix) 操作系统提供的混音器服务 KMixer 需要 log 值乘以 65,536。要提供与此功能的兼容性,我们要计算下列值,编码解码器在缩混过程中要使用这些值: W = 20 * 65536 * log10(B) X = 20 * 65536 * log10(LinearSurroundMix * B) Y = 20 * 65536 * log10(LinearCenterMix * B) Z = 20 * 65536 * log10(LinearLFEMix *B) 下表显示了这四个值与六个输入声道和两个输出声道有着怎样的关系:
作为缩混属性值的字符串具有下列格式: W,minusInfinity,minusInfinity,W,Y,Y,Z,Z,X,minusInfinity,minusInfinity,X 编码应用程序可以使用此值用于 minusInfinity: –2147483648 (0x80000000) 指定缩混属性的 Windows Media Format SDK 常量为 g_wszFold6To2Channels3。本文最后一节显示的示例代码会计算必需值、构造逗号分隔的字符串,并将该属性插入编码文件中。 动态范围控制有些音频流包含了较大的音频音量范围,用户可能想限制此声音大小。上述情况对于从经典音乐到电影原声带的各种音频源来说都可能存在。 峰值音量和平均音量之间的差别称为动态范围。如果用户启用了动态范围控制,则 Windows Media Audio Professional 编码解码器支持创作峰值音量和平均音量,这些音量将对播放过程中可用的动态范围进行控制。 注 Windows Media Audio Lossless 编码解码器还支持作者控制的动态范围控制。 对音频内容进行编码之后,Windows Media Audio Professional 编码解码器会计算该编码内容的峰值音量和平均音量。它会在文件的元数据中两次插入这些值:作为只读参考值和作为读写目标值。参考值会保留内容的原始值。如果用户启用了动态范围控制,则在解码过程中这四个值都会用到。因为目标值可以更改,所以利用编码应用程序,内容作者能够指定新值,以便在用户启用了动态范围控制的情况下调整播放。 编码应用程序应该显示参考值,以便内容作者能够选择合适的目标值。它应该对峰值目标值和平均目标值都强制使用最大值 0 dB 和最小值 -90 dB。 Windows Media Format SDK 为这四个属性提供了下列常量:
编码应用程序应该向内容作者明确表明,不建议设置平均目标值。调整这个平均值不会影响高低声音差别,而会降低或者大大提高整体平均音量,从而导致播放过程中不希望出现的失真。 播放应用程序通过使用输出设置 g_wszDynamicRangeControl 来启用动态范围控制。该应用程序使用 Reader 对象的 IWMReaderAdvanced2::SetOutputSetting 方法来配置该设置。值为零(默认值)指定不更改动态范围。值为 1 指定中等级别的动态范围压缩。值为 2 指定高级别的动态范围压缩。 注 在 Windows Media Player 9 Series 以及更高版本中,Quiet Mode 的用户界面选项决定着动态范围控制。设置 Off、Medium difference 和 Little difference 分别与 g_wszDynamicRangeControl 值 0、1 和 2 相对应。 下表说明了 g_wszDynamicRangeControl 设置在播放过程中产生的效果。
如果您要使用 Windows Media Format SDK 构建编码应用程序,则应该提供一个用户界面,以便内容作者能够指定这些目标值。然后,该应用程序应该根据需要修改 g_wszWMWMADRCPeakTarget 和 g_wszWMWMADRCAverageTarget 元数据属性。您还应该提供一个使得用户能够指定要应用的动态范围控制程度的用户界面。 代码示例下面的代码示例演示了如何使用 Windows Media Format 9 Series SDK 或更高版本来写入和读取多声道音频。 写入多声道输出 下面的示例代码演示了如何将缩混数据写入一个多声道 ASF 文件: //Some useful defines, although not all are used in this code example #define DEFAULT_SURROUND_MIX -3 #define DEFAULT_CENTER_MIX -3 #define DEFAULT_LFE_MIX -12 #define INVALID_AUDIO_VALUE 1 #define MINUS_INFINITY 0x80000000 // –2147483648 #define PLUS_INFNITY 0x7FFFFFFF // 2147483647 #define KMIXER_LOG_CONSTANT1 20.0 #define KMIXER_LOG_CONSTANT2 65536.0 #define OUT_FORMAT L"%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\0" // Name: SixToTwoFoldDown // Desc: This is the essential fold-down algorithm HRESULT SixToTwoFoldDown( long lSurroundMix, long lCenterMix, long lLFEMix, LPWSTR pwszTable, DWORD dwLen ) { if( NULL == pwszTable ) { return( E_POINTER ); } double dLinearSurroundMix, dLinearCenterMix, dLinearLFEMix; long W, X, Y, Z; double dbB; // Calculate coefficients dLinearSurroundMix = pow( 10.0, ( (double) lSurroundMix ) / KMIXER_LOG_CONSTANT1 ); dLinearCenterMix = pow( 10.0, ( (double) lCenterMix ) / KMIXER_LOG_CONSTANT1 ); dLinearLFEMix = pow( 10.0, ( (double) lLFEMix ) / KMIXER_LOG_CONSTANT1 ); dbB = 1.0 / ( 1.0 + dLinearSurroundMix + dLinearCenterMix + dLinearLFEMix ); // KMixer requires log values scaled by 65,536 W = (long) ( KMIXER_LOG_CONSTANT1 * KMIXER_LOG_CONSTANT2 * log10( dbB ) ); X = (long) ( KMIXER_LOG_CONSTANT1 * KMIXER_LOG_CONSTANT2 * log10( dLinearSurroundMix * dbB ) ); Y = (long) ( KMIXER_LOG_CONSTANT1 * KMIXER_LOG_CONSTANT2 * log10( dLinearCenterMix * dbB ) ); Z = (long) ( KMIXER_LOG_CONSTANT1 * KMIXER_LOG_CONSTANT2 * log10( dLinearLFEMix * dbB ) ); // Print out into a string. _snwprintf( pwszTable, dwLen-1, OUT_FORMAT , //L"%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\0" W, (long) MINUS_INFINITY, // L values (long) MINUS_INFINITY, W, // R values Y, Y, // C values Z, Z, // LFE values X, (long) MINUS_INFINITY, // LS values (long) MINUS_INFINITY, X ); // RS values *(pwszTable + dwLen - 1 ) = L'\0'; return S_OK; } // Name: SetFoldDownProperty // Desc: Sets the fold-down property string on the specified ASF stream HRESULT SetFoldDownProperty ( long lSurroundMix, long lCenterMix, long lLFEMix, WORD wStreamNum, IWMHeaderInfo* pHeader) { HRESULT hr; // Wide character buffer to hold the property strings WCHAR wszTable[MAX_PATH]; memset( wszTable, 0, sizeof(WCHAR) * MAX_PATH ); // Variables used in SetAttribute WMT_ATTR_DATATYPE datatype = WMT_TYPE_STRING; WORD cbLen = 0; BYTE* pData = NULL; // Check for valid input if ( ( lSurroundMix <= 0 && lSurroundMix >= -144) && ( lCenterMix <= 0 && lCenterMix >= -144) && ( lLFEMix <= 0 && lLFEMix >= -144)) { // Calculate the fold-down values and write them as a string // into the buffer provided. // In this example, we only do 5.1 to 2 fold-down. hr = SixToTwoFoldDown( lSurroundMix, lCenterMix, lLFEMix, wszTable, MAX_PATH ); if(SUCCEEDED(hr)) { cbLen = sizeof(WCHAR) * ( wcslen( pwszAttribValue ) + 1); pData = (BYTE*) wszTable; // Now set the attribute for the stream in the ASF file hr = pHeader->SetAttribute( wStreamNum, //zero-based g_wszFold6To2Channels3, datatype, pData, cbLen ); } } else { hr = E_INVALIDARG; } return hr; } 读取多声道音频 要使用 Reader 对象读取或播放多声道音频,请按以下顺序执行下面三个步骤:
这些步骤在下面的代码示例中进行了演示。Windows Media Format SDK 中的 audioplayer 示例应用程序使用 waveOut API 来呈现已经由 Reader 对象进行了分析和解码的音频。要为 audioplayer 添加多声道音频支持,请执行下列步骤:
注 如果该读取器对象设置的格式类型为 WAVEFORMATEXTENSIBLE,wFormatTag 则设置为 WAVE_FORMAT_EXTENSIBLE,cbSize 设置为 22。尽管 waveOutOpen 函数使用的指针为 WAVEFORMATEX,该函数还是会检测这两个值,并正确处理 WAVEFORMATEXTENSIBLE 结构中存在的其他数据。 更多信息要更多了解 Windows Media Player 处理动态范围信息的方式,请参阅 Microsoft 网站上的文章“Dynamic Range Control in Windows Media 9 Series”。 有关 Windows XP 中多声道音频的更多信息,请参阅 Microsoft 网站上的文章“Multiple Channel Audio Data and WAVE Files”。 |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!