古い学校のステレオVUメーターを「偽造」するために、Arduino(それ自体が5Vの電圧計に接続されている)に接続されたコンピューターを使用しようとしています。私の目標は、オーディオ ファイルを再生しているコンピューターで信号を分析し、振幅情報をシリアル接続を介して Arudino に送信し、電圧計に表示させることです。
MPD を使用してオーディオをレンダリングし、USB DAC (ODAC) に送信しています。MPD は、Python スクリプトを使用して読み取った FIFO にも出力しています。FIFO から 4096 バイトのチャンクで読み取り、audioop ライブラリを使用してそのチャンク/サンプルを左右のチャネルに分割し、各チャネルの最大振幅を計算します。
ここに問題があります。私はデータに圧倒されています。私の計算が間違っているか、FIFO がどのように機能するか (あるいはその両方) を理解していないのではないかと推測しています。MPD はすべてを 44100:16:2 形式で出力しています。これは、1 秒あたり 44,100 の 4 バイト サンプルを書き出すことを意味していると思いました。したがって、4096 バイトのチャンクを取得する場合、1 秒あたり約 43 チャンクを期待する必要があります。しかし、私はそれよりもはるかに多く (100 以上) 取得しており、チャンク サイズを大きくしても、1 秒あたりに取得するチャンクの数は変わりません。たとえば、チャンク サイズを 2 倍の 8192 にしても、1 秒あたりのチャンク数はほぼ同じです。明らかに私は何か間違ったことをしていますが、それが何であるかはわかりません。誰にも考えはありますか?
私の mpd.conf ファイルの関連部分は次のとおりです。
audio_output {
type "fifo"
name "my_fifo"
path "/tmp/mpd.fifo"
format "44100:16:2"
}
Python スクリプトは次のとおりです。
import os
import audioop
import time
import errno
import math
#Open the FIFO that MPD has created for us
#This represents the sample (44100:16:2) that MPD is currently "playing"
fifo = os.open('/tmp/mpd.fifo', os.O_RDONLY)
while 1:
try:
rawStream = os.read(fifo, 4096)
except OSError as err:
if err.errno == errno.EAGAIN or err.errno == errno.EWOULDBLOCK:
rawStream = None
else:
raise
if rawStream:
leftChannel = audioop.tomono(rawStream, 2, 1, 0)
rightChannel = audioop.tomono(rawStream, 2, 0, 1)
stereoPeak = audioop.max(rawStream, 2)
leftPeak = audioop.max(leftChannel, 2)
rightPeak = audioop.max(rightChannel, 2)
leftDB = 20 * math.log10(leftPeak) -74
rightDB = 20 * math.log10(rightPeak) -74
print(rightPeak, leftPeak, rightDB, leftDB)