我正在尝试使用连接到 Arduino(它本身连接到一些 5V 电压表)的计算机来“伪造”一个老式的立体声 VU 表。我的目标是让正在播放音频文件的计算机分析信号并通过串行连接将幅度信息发送到 Arudino,以显示在电压表上。
我正在使用 MPD 渲染音频并将其发送到 USB DAC (ODAC)。MPD 也输出到 FIFO,我使用 Python 脚本读取。我从 FIFO 中读取 4096 字节块,然后使用 audioop 库将该块/样本拆分为左右通道并计算每个通道的最大幅度。
这就是问题所在——我被数据淹没了。我猜我的数学是错误的,或者我不明白 FIFO 是如何工作的(或者可能两者兼而有之)。MPD 以 44100:16:2 格式输出所有内容——我认为这意味着它将每秒输出 44,100 个 4 字节样本。因此,如果我抓取 4096 字节的块,我应该期望每秒大约 43 个块。但是我得到的远不止这些(超过 100 个),而且如果我增加我的块大小,我每秒获得的块数不会改变。例如,如果我将我的块大小加倍到 8192,我仍然每秒获得大致相同数量的块。很明显我做错了什么,但我不知道它是什么。有人有什么想法吗?
这是我的 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)