我想用Python制作音频频谱分析仪。我使用了pyaudio库,我正在从麦克风中读取流。对于每次读取,我得到4410个值,我使用numpy转换为数字,然后将它们绘制到pygame屏幕上。看起来像这样:https://photos.google.com/share/AF1QipMCWVk1pR0dmrrsTlpE3gHQ9GTUV25MqwUxw4JuW8TrItkGkuU9X3ZpY2ZQ-RLHew?key=UE9Id19IU1dtSHZfUk43TjB3SWxFcVhRRTFYOWFB(图表颠倒了) 我的代码是:
import pyaudio, math, struct,pygame, numpy
pa = pyaudio.PyAudio()
#open audio stream
stream = pa.open(input_device_index=1,rate=44100,format=pyaudio.paInt16,channels=2,input=True)
#read bytes from stream and convert to numbers
def get_data():
data = stream.read(int(44100*0.05))
s = numpy.fromstring(data, numpy.int16)
return struct.unpack('h'*4410, data)
pygame.init()
screen = pygame.display.set_mode((4000,1000))
def redraw():
data = get_data()
#draw every number as a bar onto pygame windows
#last 4410 values are missin
for x in range(4000):
val = data[x]
pygame.draw.rect(screen,(0,0,0),(x,0,1,1000),0)
pygame.draw.rect(screen,(255,255,255),(x,0,1,val),0)
pygame.display.update()
pygame.event.clear()
while 1:
redraw()
有没有任何奇特的方法将这些4410值合并到15,所以我可以拥有漂亮的&凉爽的绿色&合理大小的窗口中的红色条形图,而不是需要3个屏幕的丑陋的东西?
答案 0 :(得分:2)
频率与时域
如上所述,您的代码会绘制样本的time-domain表示,而频谱分析器则是frequency domain表示。
时间< - >可以使用Discrete Fourier Transform实现频域转换。实际上,您需要在转换之前将Window function应用于数据。
DFT的输出是一系列大小相等的频率箱,每个频率箱包含实部和虚部。频谱分析仪通常具有相等感知宽度的频带 - 也就是说,相同数量的八度音程(或八度音程的分数)。因此,每个频带的频率区间将是之前的频率区间的两倍。 15个频段相当于每个频段2/3个八度音阶。
图形输出说明
您已经渲染了时域样本,每个样本水平使用一个像素,并且幅度直接映射到Y坐标。由于幅度范围为-32767 < x < 32768
,因此绝大多数样本将小于或大于显示屏中提供的范围0 <= x < 4000
- 因此大多数样本将被裁剪为0
或{ {1}}。
您可以通过缩放样本以使结果适合3999
来对此结果进行更正,以便500
的样本值呈现为0
的Y坐标。