使用 ALSA 和 Jack 的 M-Audio Audiophile USB 指南

v1.5

Thibault Le Meur <Thibault.LeMeur@supelec.fr>

本文档是关于如何使用 ALSA 和 JACK 操作 M-Audio Audiophile USB (tm) 设备的指南。

历史

  • v1.4 - Thibault Le Meur (2007-07-11)

  • v1.5 - Thibault Le Meur (2007-07-12) - 添加 AC3/DTS 直通信息

Audiophile USB 规格和正确用法

本部分是关于设备功能和限制的重要事实的提醒。

该设备有 4 个音频接口和 2 个 MIDI 端口

  • 模拟立体声输入 (Ai)

    • 此端口支持 2 对线路电平音频输入(1/4” TS 和 RCA)

    • 当连接 1/4” TS(插孔)连接器时,RCA 连接器将被禁用

  • 模拟立体声输出 (Ao)

  • 数字立体声输入 (Di)

  • 数字立体声输出 (Do)

  • Midi 输入 (Mi)

  • Midi 输出 (Mo)

内部 DAC/ADC 具有以下特性

  • 16 或 24 位的采样深度

  • 从 8kHz 到 96kHz 的采样率

  • 两个接口不能同时使用不同的采样深度。

此外,Audiophile USB 文档给出了以下警告

在切换位深度之前,请退出任何正在运行的音频应用程序

由于 USB 1.1 带宽限制,根据选择的音频模式,可以同时激活的接口数量有限

  • 16 位/48kHz ==> 4 个输入通道 + 4 个输出通道

    • Ai+Ao+Di+Do

  • 24 位/48kHz ==> 4 个输入通道 + 2 个输出通道,或 2 个输入通道 + 4 个输出通道

    • Ai+Ao+Do 或 Ai+Di+Ao 或 Ai+Di+Do 或 Di+Ao+Do

  • 24 位/96kHz ==> 2 个输入通道 _或_ 2 个输出通道(仅限半双工)

    • Ai 或 Ao 或 Di 或 Do

关于数字接口的重要事实:

  • Do 端口还支持环绕编码的 AC-3 和 DTS 直通,尽管我尚未在 Linux 下测试它

    • 请注意,在此设置中只能启用 Do 接口

  • 除了录制音频数字流之外,启用 Di 端口也是将设备同步到外部采样时钟的一种方式

    • 因此,只有在连接了活动的数字源时,才必须启用 Di 端口

    • 当没有连接数字源时启用 Di 可能会导致同步错误(例如,以奇数采样率播放的声音)

ALSA 中的 Audiophile USB MIDI 支持

一旦加载了以下模块,Audiophile USB MIDI 端口将自动获得支持

  • snd-usb-audio

  • snd-seq-midi

无需其他设置。

ALSA 中的 Audiophile USB 音频支持

Audiophile USB 设备的音频功能由 snd-usb-audio 模块处理。此模块可以在默认模式下工作(没有任何设备特定的参数),也可以在具有设备特定参数 device_setup 的“高级”模式下工作。

默认 Alsa 驱动程序模式

snd-usb-audio 驱动程序的默认行为是在启动时列出设备功能,并在应用程序需要时激活所需模式:例如,如果用户以 24 位深度模式录制,然后立即想要切换到 16 位深度模式,则 snd-usb-audio 模块将动态地重新配置设备。

这种方法的优点是让驱动程序根据用户的需求自动切换采样率/深度。但是,那些在 Windows 下使用该设备的人都知道,这不是该设备应该工作的方式:在 Windows 下,必须关闭应用程序,然后使用 m-audio 控制面板切换设备工作模式。因此,正如我们将在下一节中看到的那样,这种默认的 Alsa 驱动程序模式可能会导致设备配置错误。

现在让我们回到默认的 Alsa 驱动程序模式。在这种情况下,Audiophile 接口以下列方式映射到 alsa pcm 设备(我假设设备的索引为 1)

  • hw:1,0 是播放中的 Ao 和捕获中的 Di

  • hw:1,1 是播放中的 Do 和捕获中的 Ai

  • hw:1,2 是 AC3/DTS 直通模式下的 Do

在此模式下,设备使用大字节序字节编码,因此支持的音频格式为 16 位深度模式的 S16_BE 和 24 位深度模式的 S24_3BE。

一个例外是 hw:1,2 端口,据报告它符合小字节序(据称支持 S16_LE),但实际上仅处理 S16_BE 流。这已在内核 2.6.23 及更高版本中修复,现在在此默认驱动程序模式下,hw:1,2 接口报告为大字节序。

示例

  • 将 S24_3BE 编码的原始文件播放到 Ao 端口

    % aplay -D hw:1,0 -c2 -t raw -r48000 -fS24_3BE test.raw
    
  • 从 Ai 端口录制 S24_3BE 编码的原始文件

    % arecord -D hw:1,1 -c2  -t raw -r48000 -fS24_3BE test.raw
    
  • 将 S16_BE 编码的原始文件播放到 Do 端口

    % aplay -D hw:1,1 -c2 -t raw -r48000 -fS16_BE test.raw
    
  • 将 ac3 示例文件播放到 Do 端口

    % aplay -D hw:1,2 --channels=6 ac3_S16_BE_encoded_file.raw
    

如果您对默认的 Alsa 驱动程序模式感到满意,并且在此模式下没有遇到任何问题,则可以跳过以下章节。

高级模块设置

由于上述硬件限制,Alsa 驱动程序在默认模式下进行的设备初始化可能会导致设备处于损坏状态。例如,一个特别令人恼火的问题是,从 Ai 接口捕获的声音听起来失真(好像被过度的高音量增益放大)。

对于遇到此问题的人,snd-usb-audio 模块有一个名为 device_setup 的新模块参数(此参数是在内核版本 2.6.17 中引入的)

初始化 Audiophile USB 的工作模式

就 Audiophile USB 设备而言,此值允许用户指定

  • 采样深度

  • 采样率

  • 是否使用 Di 端口

当使用 device_setup=0x00 初始化时,snd-usb-audio 模块的行为与省略参数时相同(请参见上文“默认 Alsa 驱动程序模式”段落)

其他模式在以下小节中进行描述。

16 位模式

支持的两种模式是

  • device_setup=0x01

    • 禁用 Di 的 16 位 48kHz 模式

    • Ai、Ao、Do 可以同时使用

    • hw:1,0 在捕获模式下不可用

    • hw:1,2 不可用

  • device_setup=0x11

    • 启用 Di 的 16 位 48kHz 模式

    • Ai、Ao、Di、Do 可以同时使用

    • hw:1,0 在捕获模式下可用

    • hw:1,2 不可用

在此模式下,设备仅以 16 位模式运行。在内核 2.6.23 之前,设备报告为大字节序,而实际上它们是小字节序,因此播放文件需要使用

% aplay -D hw:1,1 -c2 -t raw -r48000 -fS16_BE test_S16_LE.raw

其中“test_S16_LE.raw”实际上是一个小字节序示例文件。

感谢 Hakan Lennestal(他发现了这些模式下设备的小字节序),已提交了一个修复程序(预计在内核 2.6.23 中),并且 Alsa 现在报告小字节序接口。因此,现在播放文件就像使用

% aplay -D hw:1,1 -c2 -t raw -r48000 -fS16_LE test_S16_LE.raw

24 位模式

支持的三种模式是

  • device_setup=0x09

    • 禁用 Di 的 24 位 48kHz 模式

    • Ai、Ao、Do 可以同时使用

    • hw:1,0 在捕获模式下不可用

    • hw:1,2 不可用

  • device_setup=0x19

    • 启用 Di 的 24 位 48kHz 模式

    • 可以同时使用 {Ai、Ao、Di、Do} 中的 3 个端口

    • hw:1,0 在捕获模式下可用,并且必须将活动的数字源连接到 Di

    • hw:1,2 不可用

  • device_setup=0x0D0x10

    • 24 位 96kHz 模式

    • 此模式默认启用 Di,但不需要连接到活动的源

    • 可以同时使用 {Ai、Ao、Di、Do} 中的 1 个端口

    • hw:1,0 在捕获模式下可用

    • hw:1,2 不可用

在这些模式下,设备仅符合大字节序(有关 aplay 命令示例,请参见上面的“默认 Alsa 驱动程序模式”)

AC3 w/ DTS 直通模式

感谢 Hakan Lennestal,我现在有一份报告说此模式有效。

  • device_setup=0x03

    • 仅启用 Do 端口的 16 位 48kHz 模式

    • AC3 with DTS 直通

    • 请注意,在这种设置中,Do 端口映射到 pcm 设备 hw:1,0

用于在此模式下播放 AC3/DTS 编码的 .wav 文件的命令行

% aplay -D hw:1,0 --channels=6 ac3_S16_LE_encoded_file.raw

如何使用 device_setup 参数

可以给出参数

  • 通过手动探测设备(以 root 身份):

    # modprobe -r snd-usb-audio
    # modprobe snd-usb-audio index=1 device_setup=0x09
    
  • 或者在模块配置文件中配置模块选项时(通常是 /etc/modprobe.d/ 目录中的 .conf 文件):

    alias snd-card-1 snd-usb-audio
    options snd-usb-audio index=1 device_setup=0x09
    

初始化设备时的注意事项

  • 设备上的正确初始化要求在设备开启之前将 device_setup 提供给模块。因此,如果您使用上述“手动探测”方法,请注意在完成此初始化之后再打开设备电源。

  • 不遵守此操作将导致设备配置错误。在这种情况下,请关闭设备电源,卸载 snd-usb-audio 模块,然后使用正确的 device_setup 参数再次探测它,然后再(并且仅在此时)再次打开设备电源。

  • 如果您已在有效模式下正确初始化了设备,然后想要切换到另一种模式(可能具有不同的采样深度),请也使用以下步骤

    • 首先关闭设备电源

    • 注销 snd-usb-audio 模块 (modprobe -r)

    • 通过更改 /etc/modprobe.d/*.conf 中的 device_setup 选项来更改 device_setup 参数

    • 打开设备电源

  • 针对最后一个问题的解决方法已应用于内核 2.6.23,但这可能不足以确保设备初始化的“稳定性”。

针对黑客的技术细节

本节适用于希望了解设备内部细节以及 Alsa 如何支持它的黑客。

发烧友 USB 的 device_setup 结构

如果您想了解发烧友 USB 的 device_setup 魔术数字,您需要一些二进制计算的基本知识。但是,这不是使用参数所必需的,您可以跳过本节。

device_setup 的长度为一个字节,其结构如下

+---+---+---+---+---+---+---+---+
| b7| b6| b5| b4| b3| b2| b1| b0|
+---+---+---+---+---+---+---+---+
| 0 | 0 | 0 | Di|24B|96K|DTS|SET|
+---+---+---+---+---+---+---+---+

其中

  • b0 是 SET

    • 如果初始化 device_setup,则必须设置此位

  • b1 是 DTS

    • 仅对于带有 DTS/AC3 的数字输出设置此位

    • 此设置未经过测试

  • b2 是采样率选择标志

    • 当设置为 1 时,采样率范围为 48.1-96kHz

    • 否则,采样率范围为 8-48kHz

  • b3 是位深度选择标志

    • 当设置为 1 时,采样长度为 24 位

    • 否则,采样长度为 16 位

    • 请注意,b2 暗示 b3,因为 96kHz 模式仅支持 24 位采样

  • b4 是数字输入标志

    • 当设置为 1 时,设备假定已连接有效的数字源

    • 如果端口上没有看到任何源,则不应启用 Di(这会导致同步问题)

    • b4 由 b2 暗示(由于一次仅启用一个端口,因此不会发生同步错误)

  • b5 到 b7 保留供将来使用,并且必须设置为 0

    • 可能会分别成为 b7、b6 和 b4 的 Ao、Do、Ai

注意

  • 不会对您提供给 device_setup 的值进行检查

    • 例如,选择 0x05(16 位 96kHz)将回退到 0x09,因为 b2 暗示 b3。但是 _在_/var/log/messages_ 中_不会_有_警告_

  • 不会检查由于 USB 总线限制造成的硬件约束

    • 选择 b2 将为 24 位/96kHz 准备所有接口,但您一次只能使用一个接口

此设备的 USB 实现细节

如果您对驱动程序黑客不感兴趣,可以安全地跳过本节。

本节描述了设备的一些内部方面,并总结了我通过 USB 嗅探 Windows 和 Linux 驱动程序获得的数据。

M-Audio 发烧友 USB 具有 7 个 USB 接口:一个“USB 接口”

  • USB 接口编号 0

  • USB 接口编号 1

    • 音频控制功能

  • USB 接口编号 2

    • 模拟输出

  • USB 接口编号 3

    • 数字输出

  • USB 接口编号 4

    • 模拟输入

  • USB 接口编号 5

    • 数字输入

  • USB 接口编号 6

    • 符合 MIDIMAN 怪癖的 MIDI 接口

每个接口都有 5 个备选设置(AltSet 1、2、3、4、5),但

  • 接口 3(数字输出)有一个额外的 Alset 编号 6

  • 接口 5(数字输入)没有 Alset 编号 3 和 5

以下是对 AltSettings 功能的简短描述

  • AltSettings 1 对应于

    • 24 位深度、48.1-96kHz 采样模式

    • 自适应播放(Ao 和 Do)、同步捕获 (Ai) 或异步捕获 (Di)

  • AltSettings 2 对应于

    • 24 位深度、8-48kHz 采样模式

    • 异步捕获和播放 (Ao,Ai,Do,Di)

  • AltSettings 3 对应于

    • 24 位深度、8-48kHz 采样模式

    • 同步捕获 (Ai) 和自适应播放 (Ao,Do)

  • AltSettings 4 对应于

    • 16 位深度、8-48kHz 采样模式

    • 异步捕获和播放 (Ao,Ai,Do,Di)

  • AltSettings 5 对应于

    • 16 位深度、8-48kHz 采样模式

    • 同步捕获 (Ai) 和自适应播放 (Ao,Do)

  • AltSettings 6 对应于

    • 16 位深度、8-48kHz 采样模式

    • 同步播放 (Do)、音频格式类型 III IEC1937_AC-3

为了确保设备的正确初始化,驱动程序必须知道如何使用设备

  • 如果选择 DTS,则必须仅注册带有 AltSet 编号 6 的接口 2

  • 如果使用 96KHz,则必须仅选择每个接口的 AltSet 编号 1

  • 如果采样使用 24 位/48KHz,则如果连接了数字输入,则必须使用 AltSet 2,如果未连接数字输入,则仅使用 AltSet 编号 3

  • 如果采样使用 16 位/48KHz,则如果连接了数字输入,则必须使用 AltSet 4,如果未连接数字输入,则仅使用 AltSet 编号 5

当将 device_setup 作为参数提供给 snd-usb-audio 模块时,parse_audio_endpoints 函数会使用一个名为 audiophile_skip_setting_quirk 的怪癖,以防止在驱动程序中注册不对应于 device_setup 的 AltSettings。

发烧友 USB 和 Jack 支持

本节讨论 Jack 中对发烧友 USB 设备的支持。

将 Jackd 与设备一起使用时,有两个主要的潜在问题

  • 支持 24 位模式下的 Big-Endian 设备

  • 支持 4 输入/4 输出通道

在 Jackd 中的直接支持

Jack 仅在最新版本中支持 big endian 设备(感谢 Andreas Steinmetz 的第一个 big-endian 补丁)。我不记得这项支持具体何时发布到 jackd 中,我们只说,使用 jackd 版本 0.103.0 时,它几乎可以正常工作(只是一个小错误会影响 16 位 Big-Endian 设备,但是由于您仔细阅读了以上段落,您现在使用的是内核 >= 2.6.23,并且您的 16 位设备现在是 Little Endians ;-)。

您可以运行 jackd 并使用以下命令使用 Ao 进行播放和使用 Ai 进行录制

% jackd -R -dalsa -Phw:1,0 -r48000 -p128 -n2 -D -Chw:1,1

使用 Alsa plughw

如果您没有安装最新的 Jackd,您可以降级到使用 Alsa plug 转换器。

例如,以下是一种在 Ao 上运行 2 个播放通道并从 Ai 运行 2 个捕获通道的 Jack 的方法

% jackd -R -dalsa -dplughw:1 -r48000 -p256 -n2 -D -Cplughw:1,1
但是您可能会看到以下警告消息

您似乎正在使用 ALSA 软件“plug”层,这可能是使用“default”ALSA 设备的结果。这不如它可能的那样高效。考虑使用硬件设备而不是使用 plug 层。

在 Jack 中获取 2 个输入和/或输出接口

如您所见,以这种方式启动 Jack 服务器只会启用 1 个立体声输入(Di 或 Ai)和 1 个立体声输出(Ao 或 Do)。

这是由于以下限制

  • Jack 一次只能打开一个捕获设备和一个播放设备

  • 发烧友 USB 被视为 2 个(或三个)Alsa 设备:hw:1,0、hw:1,1(可选地为 hw:1,2)

如果您想在 Jack 中获得 Ai+Di 和/或 Ao+Do 支持,则需要将 Alsa 设备组合成一个逻辑“复杂”设备。

如果您想尝试一下,我建议您阅读此页面中的信息:http://www.sound-man.co.uk/linuxaudio/ice1712multi.html 它与另一个设备 (ice1712) 有关,但可以进行调整以适应发烧友 USB。

为 Jackd 启用多个发烧友 USB 接口肯定需要

  • 确保您的 Jackd 版本具有 MMAP_COMPLEX 补丁(请参阅 ice1712 页面)

  • (可能)修补 alsa-lib/src/pcm/pcm_multi.c 文件(请参阅 ice1712 页面)

  • 在您的 .asoundrc 文件中定义一个多设备(hw:1,0 和 hw:1,1 的组合)

  • 使用此设备启动 jackd

到目前为止,我没有成功测试这一点,如果您在这种设置中获得任何成功,请给我发送电子邮件。