我想用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个屏幕的丑陋图形?

最佳答案

频域与时域

在编写时,您的代码绘制了样本的time-domain表示,而频谱分析仪则是frequency domain表示。

可以使用Discrete Fourier Transform实现时频域转换。实际上,您需要在转换之前将Window function应用于数据。

DFT的输出是一系列大小相等的频点,每个频点包含一个实部和虚部。频谱分析仪通常具有感知宽度相等的频段-即相等数量的 Octave 音阶(或 Octave 音阶的分数)。因此,每个频段中的频段将是之前频段的两倍。 15个频段相当于每个频段的2/3倍频程。

图形输出说明

您已经绘制了时域样本,每个样本水平使用一个像素,并将幅度直接映射到Y坐标。由于幅度范围是-32767 < x < 32768,因此绝大多数样本将小于或大于显示屏中提供的范围0 <= x < 4000-因此,大多数样本将被裁剪为03999

您可以通过缩放样本以使其适合并通过500对结果进行偏差来纠正此问题,以便在0的Y坐标处呈现500的样本值。

关于python - 音频频谱分析仪(4410个值,成15条),我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/44478845/

10-09 07:06