我正在尝试使用连接到Arduino(它本身连接到一些5V电压表)的计算机来“伪造”旧式立体声VU表。我的目标是让正在播放音频文件的计算机分析信号,并通过串行连接将振幅信息发送到Arudino,以显示在电压表上。
我正在使用MPD渲染音频并将其发送到USB DAC(ODAC)。 MPD也输出到FIFO,我使用Python脚本读取。我以4096字节的块读取FIFO,然后使用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)
答案 0 :(得分:2)
回答我自己的问题。事实证明,无论我指定应该读取多少字节,os.read()返回2048字节。这意味着os.read()所采用的第二个参数是它将读取的最大字节数 - 但是并不能保证那么多字节实际< / em>被阅读。我曾经想过,当我打开FIFO时,os.read()调用将等待,直到它收到文件结束或指定的字节数,从而省略了NONBLOCK选项。但事实并非如此。为了解决这个问题,我的代码现在检查os.read()返回的字节字符串的长度,并且 - 如果该长度小于我指定的块大小 - 将等待获取下一个块然后将连接在继续处理数据之前,所有块都在一起,以便我有一个与我的目标匹配的块大小。