如何在不停止的情況下更改管道的輸出文件
我正在使用 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
不幸的是,這只是告訴我“設備或資源忙”
在 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
一個新的。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
這可能很有用,因為如果您再次更改符號連結並開始保存到正常文件,很可能不會觸發彈出。
沒有或有符號連結的方法可以一起使用。When
output
是一個符號連結,只需將其刪除,下一個dd
將創建output
為正常文件。Whenoutput
是一個正常文件,並且您想用符號連結替換它而不失去數據,請將文件硬連結到一個新名稱(例如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
一兩秒。