1

我正在 matplotlib 中创建一个简单的频谱图

  1. 我想知道如何(或从哪里开始,以便学习)创建一个简单的光标跟踪器,告诉我图表峰值处的频率值。我试图重现的频谱图如下。红色的频谱标记是我想要实现的。

频谱图

我想创建一个简单的可移动垂直标记,就像上面的那个,它告诉我播放声音的频率(在某个点测量我的图表上的 x 值的东西)。

  1. 我还想知道如何插入像上面那样的暂停按钮。这应该可以使整个屏幕可以随时暂停

当前解决方案

截至目前,我的程序如下图所示。这是我用python制作的一个简单的频谱图。

好像

我的代码如下。如果有任何问题,请告诉我,因为我对 Stack Overflow 很陌生,使用这个网站对我来说非常陌生 - 我有很多东西要学!

Program: Spectrogram
"""

#preamble
import pyaudio, matplotlib.pyplot as plt, numpy as np, struct, sys
from scipy.fftpack import fft

#set constants
CHUNK = 1024 * 2    #samples per frame
FORMAT = pyaudio.paInt16    #audio format
CHANNELS = 1    #single channel for microphone
RATE = 44100    #samples per second

#create matplotlib figure and axes
fig, (ax, ax2) = plt.subplots(2, figsize=(10, 7))

p = pyaudio.PyAudio()
plt.ion()

#stream object to get data from microphone
stream = p.open(
    format=FORMAT,
    channels=CHANNELS,
    rate=RATE,
    input=True,
    output=True,
    frames_per_buffer=CHUNK
)

# variables for plotting
x = np.arange(0, 2 * CHUNK, 2)  #samples for waveform
x_fft = np.linspace(0, RATE, CHUNK) #frequencies for spectrum

#create a line object with random data
line, = ax.plot(x, np.random.rand(CHUNK), 'b-', lw=1)

#create a semilog x line for spectrum
line_fft, = ax2.semilogx(x_fft, np.random.rand(CHUNK), 'b-', lw=1)

#axes formatting for waveform
ax.set_title('Audio Waveform')
ax.set_xlabel('Samples')
ax.set_ylabel('Volume')
ax.set_xlim(0, 2 * CHUNK)
ax.set_ylim(0, 255)
plt.setp(ax, xticks=[0, CHUNK, 2 * CHUNK], yticks=[0, 128, 255])

#axis formatting for spectrum
ax2.set_title('Audio Spectrum')
ax2.set_xlabel('Frequency (Hz)')
ax2.set_ylabel('Volume')
ax2.set_xlim(20, RATE/2)
ax2.set_ylim(0, 1.2)
#ax2.set_xticks(np.arange(50, 1000, 50))
#ax2.grid(True, which='both')

#show plot
plt.tight_layout()
plt.show(block=False)

# close stuff
def handle_close(evt):
    sys.exit()
fig.canvas.mpl_connect('close_event', handle_close)

while True:
    #binary data
    data = stream.read(CHUNK, False)

    #convert data to integers
    data_int = struct.unpack(str(2 * CHUNK) + 'B', data)

    #create np array and offset by 128
    data_np = np.array(data_int, dtype='b')[::2] + 128

    line.set_ydata(data_np)

    #compute FFT and update line
    y_fft = fft(data_int)
    line_fft.set_ydata(np.abs(y_fft[0:CHUNK]) / (128 * CHUNK))

    #update figure canvas
    plt.pause(.0001)
    plt.show()
4

0 回答 0