1

I am creating a simple spectrogram in matplotlib

  1. I am wondering how (or where to start, in order to learn) to create a simple cursor tracker that tells me the frequency value at peaks of my graph. The spectrogram I am trying to reproduce is below. The spectrum marker in red is what I am trying to achieve.

spectrogram

I would like to create a simple movable vertical marker like the one above, which tells me what frequency my sound is played at(something that measures the x-value on my graph at a certain point).

  1. I also want to know how to insert a pause button like the one above. That should function such that the entire screen can be paused at any time

Current Solution

As of now, my program looks like the image below. It's a simple spectrogram I made in python.

looks like

My code is below. Please let me know if there are any problems with it, as I'm very new to Stack Overflow and using this site is all very foreign to me - I've much to learn!

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()
7
  • 1
    I think about the cross-hair this is a start for you matplotlib.org/3.1.3/gallery/misc/cursor_demo_sgskip.html Commented Feb 17, 2020 at 18:04
  • Please, include the code of what you have tried so far Commented Feb 17, 2020 at 18:38
  • @HenriqueHBR I've updated the post with the code. Thanks! Commented Feb 17, 2020 at 21:04
  • @eusoubrasileiro awesome, I'll check out the link! Commented Feb 17, 2020 at 21:04
  • 1
    "Please let me know if there are any problems with it, as I'm very new to Stack Overflow and using this site is all very foreign to me - I've much to learn!" - This is not what Stack Overflow is for. Please see stackoverflow.com/help/on-topic Commented Feb 18, 2020 at 14:23

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.