如何在不停止的情况下更改管道的输出文件

如何在不停止的情况下更改管道的输出文件

我正在使用 arecord 获取音频文件来执行 DSP。问题是,每次我开始从 i2s 麦克风捕获输入时,文件开头都会有 1 秒的爆音。我正在尝试使用管道来解决这个问题。我想做的是在不停止管道的情况下更改管道的输出,以避免这种流行音乐并避免音频出现间隙。

例如,我想做这样的事情来在 soundfile1 和 soundfile2 之间切换,这样我就可以在一个文件正在录制时分析另一个文件。我不关心开始录音时是否会出现爆音,但我不能每次来回切换时都会出现爆音。

arecord -D dmic_sv -c2 -r 48000 -f S32_LE -t wav -V mono -v > soundfile1.wav

arecord -D dmic_sv -c2 -r 48000 -f S32_LE -t wav -V mono -v > soundfile2.wav

不幸的是,这只是告诉我“设备或资源繁忙”

答案1

在 shell 中运行并让它运行:

arecord -D dmic_sv -c2 -r 48000 -f S32_LE -t wav -V mono -v \
| while :; do dd bs=384000 count=1 iflag=fullblock 2>/dev/null >>output; done

每个dd将向output.重要的是output将为每个单独打开并附加dd。这意味着当您rm outputmv output soundfile1.wav时,下一个dd将写入outputanew,即将output创建一个新的。

如果mv output soundfile1.wav发生在单个文件系统内,则不会丢失任何数据。我的意思是,如果您连接soundfile1.wav新的流,output那么您将重新创建原始流。这是因为重命名(甚至删除)文件不会打扰已经打开该文件的进程。

移动到另一个文件系统实际上相当于cp+ unlink。在这种情况下,可能会在和之间发生一些dd添加,并且该块会丢失。因此,不要直接移动到另一个文件系统。如果需要执行此操作,请在单个文件系统中重命名,等待新文件出现,然后才将重命名的文件移动到其他文件系统。outputcpunlinkoutputoutput

另一种方法是使用符号链接。建立output一个指向某个名称的符号链接:

ln -s soundfile2.wav output

然后运行命令。目标文件可能不存在,它将被创建。如果存在,则数据将附加到其中。

当您想切换到另一个文件时,请自动更新符号链接:

ln -sf soundfile3.wav output

新文件可能位于另一个文件系统上,但这并不重要。符号链接还允许您在不停止的情况下停止保存数据arecord。只需将我们不断运行的命令重定向到/dev/null

ln -sf /dev/null output

这可能很有用,因为如果您再次更改符号链接并开始保存到常规文件,很可能不会触发弹出窗口。

不带或带符号链接的方法可以一起使用。当output是符号链接时,只需将其删除,下一个dd将创建output为常规文件。当output是常规文件并且您想用符号链接替换它而不丢失数据时,请将文件硬链接到新名称(例如ln output soundfile4.wav),然后自动替换output为符号链接。

笔记:

  • iflag=fullblock不便于携带。如果您dd不支持它,请尝试bs=8 count=48000。无论如何,我们不希望在样本中间发生到新文件的转换。我们的一个样本为 8 字节(32 位乘以 2 个通道)。我对 Linux 中的管道不够熟悉arecord,我只能希望该工具永远不会将一个样本拆分为多次写入,因此dd bs=8即使没有iflag=fullblock.但我不确定。如果dd读得少(比较)那么它将能够结束写入中间样本,如果您更改为新文件,那么新文件将以不完整的样本开始并且无法正确播放。所以如果你能用iflag=fullblock那就用它。记住dd是一个难以正确使用的古怪工具;iflag=fullblock减少暴躁。
  • 您可以更改bs和/或count增加或减少粒度。例如,每秒bs=38400 count=1运行 10 个dd进程,因此整个设置几乎可以立即切换到新文件。另一方面,每秒 10 个进程可能是不必要的负担。任何适合你的。只要保留bs8的倍数就可以了。
  • Ctrl当您使用+终止命令时C,当前dd可以退出而不写入。您bs=384000 count=1可能会丢失最多约 1 秒的已捕获数据。在记录重要内容时,将Ctrl+推迟C一两秒。

相关内容