我正在使用 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 output
或mv output soundfile1.wav
时,下一个dd
将写入output
anew,即将output
创建一个新的。
如果mv output soundfile1.wav
发生在单个文件系统内,则不会丢失任何数据。我的意思是,如果您连接soundfile1.wav
新的流,output
那么您将重新创建原始流。这是因为重命名(甚至删除)文件不会打扰已经打开该文件的进程。
移动到另一个文件系统实际上相当于cp
+ unlink
。在这种情况下,可能会在和之间发生一些dd
添加,并且该块会丢失。因此,不要直接移动到另一个文件系统。如果需要执行此操作,请在单个文件系统中重命名,等待新文件出现,然后才将重命名的文件移动到其他文件系统。output
cp
unlink
output
output
另一种方法是使用符号链接。建立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 个进程可能是不必要的负担。任何适合你的。只要保留bs
8的倍数就可以了。 - Ctrl当您使用+终止命令时C,当前
dd
可以退出而不写入。您bs=384000 count=1
可能会丢失最多约 1 秒的已捕获数据。在记录重要内容时,将Ctrl+推迟C一两秒。