axfer-transfer - 声音设备和节点的音频数据帧的传输者。
axfer transfer direction [ common-options ] [ backend-options ] [ filepath ]
axfer transfer direction [ common-options ] [ backend-options ] -I | --separate-channels filepath ...
direction = capture | playback
common-options = ( read OPTIONS section )
backend-options = ( read OPTIONS section )
filepaths = ( read OPTIONS section )
axfer 的 transfer 子命令为支持的后端中可用的设备执行音频数据帧的传输。该程序本质上是为了使用 alsa-lib API(libasound 后端)来处理 Linux 声音子系统 (ALSA) 支持的声音设备。
用于捕获传输。
用于播放传输。
如果文件路径不是根目录的完整路径,则将其处理为相对于运行时当前工作目录的路径。
如果未指定文件路径或给定为 '-' ,则使用标准输入或输出。
对于播放传输,会自动检测给定文件路径的容器格式,并将元数据用于样本格式、通道、速率、持续时间等参数。如果未检测到任何内容,则给定文件路径的内容将作为原始数据处理。在这种情况下,参数应指示为选项。
-I | 允许多个文件路径 --separate-channels 选项。在这种情况下,标准输入和输出不可用。除了下面列出的路径之外,不允许使用相同的文件路径: - /dev/null - /dev/zero - /dev/full - /dev/random - /dev/urandom
打印帮助消息并完成运行时间。
静音模式。抑制消息(不是声音:))
详细模式。运行时根据命令行中给出的此选项的编号转储补充信息。
# 秒后中断。零值意味着无穷大。默认值为零,因此如果省略此选项,则传输进程将运行直到被终止。 -d 或 -s 选项仅可用。
传输 # 个数据帧后中断。零值意味着无穷大。默认值为零,因此如果省略此选项,则传输进程将运行直到被终止。 -d 或 -s 选项仅可用。
指示音频样本的格式。这是捕获传输或包含原始音频数据的文件的回放传输所必需的。
下面列出了可用的示例格式: - [S8|U8|S16|U16|S32|U32][_LE|_BE] - [S24|U24][_LE|_BE] - FLOAT[_LE|_BE] - FLOAT64[_LE|_BE ] - IEC958_SUBFRAME[_LE|_BE] - MU_LAW - A_LAW - [S20|U20][_LE|_BE] - [S24|U24][_3LE|_3BE] - [S20|U20][_3LE|_3BE] - [S18|U18 ][_3LE|_3BE] - DSD_U8 - DSD_[U16|U32][_LE|_BE]
如果省略字节序,则使用主机字节序。
提供一些特殊格式: - cd(16 位小端,44100,立体声)[= -f S16_LE -c 2 -r 44100] - cdr(16 位大端,44100,立体声)[= -f S16_BE -c 2 -f 44100] - dat(16 位小端,48000,立体声)[= -f S16_LE -c 2 -r 48000]
如果省略,U8 将用作默认值。实际可用的格式受每个传输后端的限制。
下面列出了不可用的示例格式。这些格式的数据帧大小与字节单元不对齐。
- IMA_ADPCM - MPEG - GSM - 特别 - G723_24 - G723_24_1B - G723_40 - G723_40_1B
指示每帧音频数据样本的数量。这是捕获传输或包含原始音频数据的文件的回放传输所必需的。该值应介于 1 到 256 之间。如果省略,则使用 1 作为默认值。
表示每秒音频数据帧的数量。这是捕获传输或包含原始音频数据的文件的回放传输所必需的。如果该值小于 1000 ,则以 kHz 为单位进行解释。该值应介于 2000 和 192000 之间。如果省略,则使用 8000 作为默认值。
指示文件类型。这是捕获传输所必需的。下面列出了可用的类型: - wav:Microsoft/IBM RIFF/Wave 格式 - au、sparc:Sparc AU 格式 - voc:Creative Tech。语音格式-raw:原始数据
当没有指定任何内容时,对于捕获传输,根据 filepath 的后缀决定类型,并使用 raw 类型进行回退。
当要处理多个文件时指示此选项。对于捕获传输,如果将一个文件路径指定为 filepath ,则会以公式“
如果后端支持,则转储硬件参数并完成运行时间。
从下面的列表中选择传输后端。默认是libasound。
- libasound - libffado (如果编译则可选)
该选项用于选择libasound配置空间中的PCM节点。可用节点由 list 子命令的 pcm 操作列出。
使用此选项,PCM子流以非阻塞模式打开。当PCM子流的缓冲区中没有可用的音频数据帧时,I/O操作立即返回,而不会阻塞过程。此选项还隐式使用 --waiter-type 选项来防止大量消耗 CPU 时间。
使用此选项,如果所选节点支持此操作,则直接在 PCM 子流的缓冲区中处理音频数据帧。如果没有该选项,临时缓冲区用于将音频数据帧复制到 PCM 子流的缓冲区。此选项还隐式使用 --waiter-type 选项来防止大量消耗 CPU 时间。
此选项将给定值配置为 PCM 子流的period_size硬件参数。该参数表示PCM子流缓冲区中每周期音频数据帧的数量。实际数量取决于从所选 PCM 节点链接的每个 PCM 插件实现与内核驱动程序或 PCM I/O 插件之间的交互结果。
理想情况下,应在一次 I/O 操作中处理与该值相同数量的音频数据帧。实际上,并非如此,具体取决于 PCM 插件、内核驱动程序、PCM I/O 插件和调度模型的实现。对于“irq”调度模型中的“hw”PCM 插件,该值用于决定硬件中断的间隔,因此一次 I/O 操作预计可使用与该值相同数量的音频数据帧。
此选项将给定值配置为 PCM 子流的period_time硬件参数。该选项与--period-size选项类似,但其单位是微秒。
此选项将给定值配置为 PCM 子流的 buffer_size 硬件参数。该参数表示PCM子流缓冲区中音频数据帧的数量。实际数量取决于从所选 PCM 节点链接的每个 PCM 插件实现与内核驱动程序或 PCM I/O 插件之间的交互结果。
理想情况下,这是每个周期的音频数据帧数量的倍数,也就是周期大小的倍数。实际上,并非如此,具体取决于 PCM 插件、内核驱动程序和 PCM I/O 插件的实现。
此选项将给定值配置为 PCM 子流的 buffer_time 硬件参数。该选项与--buffer-size选项类似,但其单位是微秒。
该选项指示事件通知的等待者类型。目前有四种类型; default 、 select 、 poll 和 epoll 。对于默认类型,使用“snd_pcm_wait()”。对于 select 类型,使用“select(2)”系统调用。对于poll类型,使用'poll(2)'系统调用。对于 epoll 类型,使用 Linux 特定的“epoll(7)”系统调用。
此选项应对应于 --nonblock 或 --mmap 选项之一,或 --sched-model< 的 timer 值/em> 选项。此选项和 --test-nowait 均不能同时可用。
该选项选择该程序进程的调度模型。 irq 或定时器 之一可用。详细内容请阅读“调度模型”部分。
如果未指定任何内容,则使用irq模型。
该选项将给定值配置为 PCM 子流的 avail-min 软件参数。在阻塞模式下,该值用作PCM子流缓冲区中可用音频数据帧数量的阈值,以唤醒被I/O操作阻塞的进程。在非阻塞模式下,任何I/O操作都会返回-EAGAIN,直到可用的音频数据帧数量达到阈值。
在既不使用 --mmap 也不使用 --sched-model 选项的 timer 值的情况下,此选项有效。
此选项将给定值配置为 PCM 子流的 start_threshold 软件参数。该值作为自动启动PCM子流的阈值。目前,此选项在既不使用 --mmap 也不使用 --sched-model 选项的 timer 值的情况下有效。
对于播放传输,当程序写入的 PCM 子流的缓冲区中累积的音频数据帧数量达到阈值时,PCM 子流自动启动,无需显式调用 PCM 的snd_pcm_start()子流。
对于捕获传输来说,这个选项是没有用的。如果没有显式调用 PCM 子流的 snd_pcm_start() ,累积的音频数据帧的数量不会增加。
在既不使用 --mmap 也不使用 --sched-model 选项的 timer 值的情况下,此选项有效。
此选项将给定值配置为 PCM 子流的 stop_threshold 软件参数。该值作为自动停止PCM子流的阈值。目前,此选项在既不使用 --mmap 也不使用 --sched-model 选项的 timer 值的情况下有效。
对于捕获传输,当驱动程序或 alsa-lib PCM 插件写入的 PCM 子流缓冲区中累积的音频数据帧数量达到阈值时,PCM 子流自动停止,无需显式调用 snd_pcm_stop() 到 PCM 子流。这是该程序暂时不读取音频数据帧的情况。
对于播放传输,当驱动程序或 alsa-lib PCM 插件读取的 PCM 子流缓冲区中的可用音频数据帧数量达到阈值时,PCM 子流自动停止,无需显式调用 snd_pcm_stop() 到 PCM 子流。这是该程序暂时不写入音频数据帧的情况。
在既不使用 --mmap 也不使用 --sched-model 选项的 timer 值的情况下,此选项有效。
此选项对 alsa-lib 中的“plug”插件有影响,可以抑制音频数据帧采样率的转换。
此选项对 alsa-lib 中的“plug”插件有影响,可以抑制音频数据帧的通道转换。
此选项对 alsa-lib 中的“plug”插件有影响,可以抑制音频数据帧的样本格式转换。
此选项对 alsa-lib 中的“softvol”插件有影响,可以通过附加控制元素抑制音频数据帧样本的转换。
该选项禁止从运行 PCM 子流的 XRUN 状态进行恢复操作,然后该程序的处理将照常完成。
此选项禁用任何 I/O 事件通知的等待程序。迭代 I/O 操作直到任何音频数据帧可用。该选项会带来沉重的 CPU 时间消耗负载。
当配置脚本检测到 libffado 共享对象中的 ffado_streaming_init() 符号时,此后端将自动可用。
该选项使用给定值来决定使用哪个 1394 OHCI 控制器进行通信。当Linux系统有两个1394 OHCI控制器时,0或1可用。此选项和 -g 不能同时使用。如果未指定任何内容,libffado 会与 Linux 系统中所有可用的 1394 OHCI 控制器管理的 IEEE 1394 总线上的单元进行通信。
该选项使用给定值来决定使用哪个单元进行通信。此选项需要 -p 选项来指示使用哪个 1394 OHCI 控制器与指定单元进行通信。
该选项使用给定值来决定要通信的目标单元。该值应以“0x”为前缀,并由十六进制文字字母(0-9、a-f、A-F)组成。此选项和 -p 不能同时使用。如果未指定任何内容,libffado 会与 Linux 系统中所有可用的 1394 OHCI 控制器管理的 IEEE 1394 总线上的单元进行通信。
该选项使用给定的值来决定一次读/写操作中音频数据帧的数量。该操作将被阻塞,直到可用音频数据帧的数量超过给定值。默认情况下,使用 512 个音频数据帧。
该选项使用给定值来决定该程序和 libffado 之间的中间缓冲区的大小。默认情况下,每个缓冲区使用 2 个周期。
该选项允许该程序运行从机模式。在这种模式下,libffado将单元目录添加到Linux系统运行的1394 OHCI控制器的配置ROM中。同一总线上的其他节点可以找到该单元目录。节点上运行的Linux系统可以将带有音频数据帧的同步数据包传输到单元。该程序可以接收数据包并解复用音频数据帧。
该选项允许该程序运行监听模式。在此模式下,libffado 监听设备传输同步数据包的同步通道。当同一总线上的任何单元开始同步通信时,该程序可以处理数据包。
此选项在调用 ffado_streaming_init() 时执行 pthread_setschedparam(),以配置调度策略并给定值作为与同步通信相关的线程的优先级。给定值应在进程的RLIMIT_RTPRIO参数范围内。请阅读getrlimit(2)了解详细信息。
在传输过程中,SIGINT 和 SIGTERM 将关闭已处理的文件和 PCM 子流以完成运行时间。
SIGTSTP 将暂停 PCM 子流,SIGCONT 将恢复它。预计不会有 XRUN。对于 libffado 后端,不支持挂起/恢复,并且运行时会立即中止。
其他信号执行默认行为。
$ axfer transfer playback -d 1 something上面将传输“something”文件中的音频数据帧,以便在 1 秒内播放。只要样本格式符合 Microsoft/IBM RIFF/Wave、Sparc AU、Creative Tech 之一,就会自动检测样本格式作为解析“某物”的结果。语音格式。如果未检测到任何内容,则应给出 -r 、 -c 和 -f ,或者应给出 -f具有特殊格式。
$ axfer transfer playback -r 22050 -c 1 -f S16_LE -t raw something上面将在“something”文件中传输音频数据帧,不包括样本格式的信息,如 22050 Hz、单声道、签名 16 位小端 PCM 的样本格式用于播放。传输将继续,直到从键盘捕获 SIGINT 或通过 kill(1) 捕获 SIGTERM 。
$ axfer transfer capture -d 10 -f cd something.wav上面的代码将在 10 秒内将音频数据帧传输到“something.wav”文件,作为 44.1 kHz、2 通道、签名 16 位小端 PCM 的示例格式。根据给定 文件路径 的后缀,文件格式为 Microsoft/IBM RIFF/Wave。
$ axfer transfer capture -s 1024 -r 48000 -c 2 -f S32_BE -I -t au channels以上将音频数据帧作为 48.0 kHz、2 通道、签名 32 位大端 PCM 的示例格式(1,024 个数据帧)传输到名为“channels-1.au”和“channels-2.au”的文件。
在ALSA PCM核的设计中,PCM子流的运行时支持两种模式; period-wakeup和no-period-wakeup这两种模式适用于不同的调度模型。
默认情况下,使用周期唤醒模式。在此模式下,内核驱动程序应操作硬件来生成音频数据帧传输的定期通知。通知间隔相当于一段缓冲时间与实际时间相同数量的音频数据帧。
在分配给通知的处理程序中,调用ALSA PCM核心的辅助函数来更新硬件传输头部的位置,然后将其与应用程序操作头部的位置进行比较,以判断溢出/欠载(XRUN)并唤醒阻塞的进程。
为此,通常使用串行音频总线(例如 Inter-IC 声音)控制器的硬件 IRQ。在这种情况下,控制器根据串行音频总线上的传输来生成IRQ。在分配给 IRQ 的处理程序中,请求在专用主机内存和设备内存之间进行直接媒体访问 (DMA) 传输。
如果目标硬件不支持这种机制,那么周期性通知应该由任何定时器来模拟;例如hrtimer,内核定时器。 alsa-lib 中的 PCM 插件 SDK 生成的外部 PCM 插件也应该模拟上述行为。
在此模式下,PCM 应用程序根据典型的 I/O 操作方式进行编程。它们执行阻塞系统调用来读/写PCM子流缓冲区中的音频数据帧,或者阻塞系统调用以等待任何音频数据帧可用。在 axfer 中,这称为基于 IRQ 的调度模型和默认行为。用户可以通过使用带有 irq 值的 --sched-model 选项显式配置此模式。
no-period-wakeup模式是PCM子流运行时的可选模式。该模式假定硬件的特定功能以及内核驱动程序和 PCM 应用程序的协助。在此模式下,内核驱动程序不会操作硬件来生成音频数据帧传输的定期通知。硬件应自动继续传输音频数据帧,而无需定期操作驱动程序;例如根据自动触发的 DMA 传输,注册描述符链。
在这种模式下,没有任何东西可以唤醒阻塞的进程,因此PCM应用程序应该在没有任何阻塞操作的情况下进行编程。因此,当 PCM 应用程序显式配置 PCM 子流运行时的硬件参数时,会启用此模式,以防止现有应用程序混乱。此外,没有任何东西可以维持音频数据帧传输的定时,因此 PCM 应用程序应自动处理任何计时器,以将音频数据帧在 PCM 子流的缓冲区中排队等待时间流逝。此外,PCM应用程序应该调用ALSA PCM核心的辅助函数来更新硬件传输头的位置并检查XRUN,而不是驱动程序。
在axfer中,这称为基于定时器的调度模型,只要硬件/驱动程序协助无周期唤醒运行时就可用。用户应通过使用 --sched-model 选项和 timer 值来显式设置此模式。
在调度模型中,PCM 应用程序需要随着时间的流逝来处理 PCM 缓冲区上的可用空间,通常是通过让出 CPU 并等待重新调度。对于让步,计算超时以获取要处理的最佳数量的 PCM 帧。这对于一种应用程序来说很方便,比如声音服务器。当服务器的I/O线程等待超时时,其他线程可以为服务器客户端处理音频数据帧。此外,通过使用倒带/转发,即使应用程序使用大尺寸的 PCM 缓冲区,也可以实现传输位置和处理位置之间的低延迟。
理想情况下,基于定时器的调度模型比基于IRQ的调度模型具有一些优势。首先,PCM 子流没有中断上下文运行。 PCM 子流仅在任何进程上下文中处理。无需关心 IRQ 和进程上下文之间的竞争条件。这减少了一些驱动程序和应用程序开发人员的担忧。其次,CPU 时间不用于中断上下文中的处理程序。 CPU 时间可以专用于其他任务。这在分时系统中是很好的一点。第三,硬件未配置为生成中断。这在可能降低整体功耗方面是有利的。
在任一调度模型中,硬件应允许驱动程序读取在专用存储器和音频串行总线的设备存储器之间传输的音频数据帧的数量。然而,在基于定时器的调度模型中,值的细粒度和准确性非常重要。实际上,硬件在专用内存和设备内存之间执行小批量音频数据帧或字节的传输。从PCM应用的角度来看,需要电流传输的粒度来决定每个I/O操作的正确超时。从 Linux 内核 v4.21 开始,内核/用户空间之间的 ALSA PCM 接口没有报告它的功能。
axfer 的 transfer 子命令旨在保持与 aplay(1) 的兼容性。但是,由于多种技术原因,以下某些选项不兼容。
仅存储与每个通道对应的音频数据帧的文件支持此选项。在 aplay(1) 实现中,如果目标设备支持,此选项具有使用与非交错顺序对齐的 PCM 缓冲区的附加效果。截至 2018 年,声音设备几乎不使用非交错顺序的 PCM 缓冲区。
该选项指示以音频数据帧为单位唤醒阻塞进程的阈值。对于 aplay(1) 实现,此选项对 --mmap 选项以及 --sched-model 选项的 timer 没有影响。
该选项指示以音频数据帧为单位启动准备好的PCM子流的阈值。对于 aplay(1) 实现,此选项对 --mmap 选项以及 --sched-model 选项的 timer 没有影响。
该选项指示以音频数据帧为单位停止运行PCM子流的阈值。对于 aplay(1) 实现,此选项对 --mmap 选项以及 --sched-model 选项的 timer 没有影响。
不支持此选项。在aplay(1)实现中,该选项对捕获传输有影响,以将文件保存到与以秒为单位的给定值相同数量的数据帧,或者所使用的文件格式支持的最大数据帧数量。当达到限制时,关闭已使用的文件,然后打开新文件并写入音频数据帧。然而,此选项需要额外的文件处理,并且会增加 axfer 主循环的复杂性。
不支持此选项。在aplay(1)实现中,该选项对捕获传输有影响,以根据给定格式生成文件路径,其中一些额外格式可用以及strftime(3)支持的格式。但该选项需要对文件路径进行额外的字符串处理,如果用C语言编写则比较麻烦。
不支持此选项。在 aplay(1) 实现中,该选项的作用是为给定值创建一个文件并向其中写入进程 ID。该文件允许用户获取进程 ID 并向 aplay 进程发送任何 POSIX 信号。然而,当多个 aplay 进程运行同一个文件时,这种想法对于文件锁定来说存在一些麻烦。
目前不支持此选项。在 aplay(1) 实现中,此选项具有使用某些终端控制字符占用标准输出并显示单声道和立体声通道的音量计的效果。然而,也存在一些问题;此功能仅适用于 PCM 格式的音频数据帧,此功能会导致中止后终端混乱,stdout 不可用于管道。
目前不支持此选项。在aplay(1)实现中,该选项的作用是占用stdin进行按键输入,并根据按下的回车键暂停/恢复PCM子流。然而,此功能需要在主循环中进行额外的输入处理,并留下麻烦的操作来维护 PCM 子流。
ALSA PCM 核心和控制核心不支持此功能,因此应在用户空间中完成重新映射。这会带来对齐音频数据帧的开销,特别是对于 mmap 操作。此外,从 alsa-lib v1.1.8 开始,一些插件不支持该功能,因此该选项缺乏透明操作。目前还不支持该选项,以免混淆用户。
这将执行 PCM 子流的暂停/恢复。在aplay(1)实现中,这些操作将XRUN状态带入子流,并且挂起/恢复是在上面的交互模式下完成的。一些开发人员使用来自 XRUN 的信号进行恢复测试。目前,测试不支持任何替代方案。
不支持此操作。在 aplay(1) 实现中,该信号被分配给处理程序以关闭当前文件以存储音频数据帧并打开新文件以继续处理。但是,与 --max-file-time 选项一样,此选项会增加 axfer 主循环的复杂性。
该计划由三个模块组成; xfer 、映射器 和容器 。每个模块都有一个抽象层来实现实际的实现。
-------- ---------- -------------
device <-> | xfer | <-> | mapper | <-> | container | <-> file
-------- ---------- -------------
libasound single wav
libffado multiple au
voc
rawxfer模块执行到设备和节点的实际传输。该模块可以有多个传输后端。作为默认后端,libasound 后端用于通过 alsa-lib API 执行传输。该模块允许每个后端解析自己的命令行选项。
容器模块通过多媒体容器的文件/流或原始数据的描述符来读取/写入音频数据帧。该模块自动检测多媒体容器的类型并解析其数据头元数据中的参数。目前支持三种类型的多媒体容器; Microsoft/IBM RIFF/Wave ( wav )、Sparc AU ( au ) 和 Creative Technology 语音 ( voc )。此外,还为原始音频数据(raw)准备了一个特殊的容器。
mapper模块处理音频数据帧传输的缓冲区布局和对齐。该模块有两种实现方式; 单个和多个。 单一后端使用一个容器来构建缓冲区。 多个后端使用多个容器来构建它。
在xfer模块和mapper模块之间,传递一个指向包含音频数据帧的缓冲区的指针。该缓冲区有两种形状,分别用于交错和非交错顺序。对于前者,指针指向一个缓冲区。对于后者,指针指向一个数组,其中每个元素都指向一个缓冲区。在mapper模块和container模块之间,会传递一个指向一个缓冲区的指针,因为支持的媒体容器(包括原始类型)以交错顺序存储音频数据帧。
在模块之间传递音频数据帧时,axfer 被编程为尽可能避免在一个缓冲区到另一个缓冲区之间进行复制。例如,在下面的某些场景中,模块之间不会发生复制。
- xfer(mmap/交错)、映射器(单个)、容器(任意) - xfer(mmap/非交错)、映射器(多个)、容器(任意)
对于每个映射器和容器模块,单元测试都是可用的。要运行测试,请执行以下命令:
$ make test每个测试都会多次迭代写入文件和读取文件,并且需要很长时间才能完成。如果在任何 CI 环境中运行,请注意执行时间。
axfer(1), axfer-list(1), alsamixer(1), amixer(1)
坂本隆