title: How to redraw pcolormesh (spectrogram) of wav file (Streaming music) (Python)
body: <p>I am running into an issue. I am attempting to stream the spectrogram of a wavfile as it plays. Basically, I want to animate the pcolormesh (spectrogram) by redrawing the graph over time. However, the figure is not redrawing the plot, and, in some cases, gets pretty choppy when playing the file.</p>
  <p>Code:</p>
  <pre><code>import scipy.io.wavfile as wavfile
  from scipy.signal import get_window, spectrogram
  
  import numpy as np
  
  import wave
  import pyaudio
  
  import matplotlib.pyplot as plt
  from matplotlib import animation
  
  # Constants
  CHUNK = 2**12
  M = 2**11
  H = M/2
  
  # Song 
  # song_wav = 'Smooth Criminal (Glee Cast Version).wav'
  song_wav = 'Perish Song (Extended).wav'
  (fs,data) = wavfile.read(song_wav)
  
  w = get_window('hamming',M)
  
  (freq,t,Sxx_l) = spectrogram(data[:,0],fs,nperseg=M,noverlap=H,window='hamming',nfft=CHUNK)
  (_,_,Sxx_r) = spectrogram(data[:,1],fs,nperseg=M,noverlap=H,window='hamming',nfft=CHUNK)
  
  # Animation of the data (Streaming)
  wf = wave.open(song_wav,'rb')
  RATE = wf.getframerate()
  CHANNELS = wf.getnchannels()
  
  # instantiate PyAudio (1)
  p = pyaudio.PyAudio()
  
  # open stream (2)
  stream = p.open(format=p.get_format_from_width(wf.getsampwidth()),
                  channels=CHANNELS,
                  rate=RATE,
                  input=True,
                  output=True,
                  frames_per_buffer=CHUNK)
  
  fig, (ax1,ax2) = plt.subplots(2, figsize=(15, 7))
  
  frmTime = 3
  numFrames = int(frmTime*fs/H)
  frmLength = frmTime*np.arange(0,numFrames)/numFrames
  frmLength = len(np.reshape(frmLength,(len(frmLength),1)))
  
  buf_zero = np.zeros((int(CHUNK/2+1),frmLength))
  
  cycles = int(len(data)/CHUNK)
  if len(data)%CHUNK != 0:
      cycles += 1
      
  # Buffer
  stream_l = []
  stream_r = []
  
  for i in range(frmLength):
      stream_l.append(np.array(np.zeros(M+1)))
      stream_r.append(np.array(np.zeros(M+1)))
      
  for i in range(len(Sxx_l[0,:])):
      stream_l.append(np.array(Sxx_l[:,i]))
      stream_r.append(np.array(Sxx_r[:,i]))
      
  for i in range(frmLength):
      stream_l.append(np.array(np.zeros(M+1)))
      stream_r.append(np.array(np.zeros(M+1)))
      
  stream_l = np.array(stream_l)
  stream_r = np.array(stream_r)
  
  left_spec = ax1.pcolormesh(t[0:frmLength],freq,np.transpose(stream_l[0:frmLength,:]), shading='gouraud')
  right_spec = ax2.pcolormesh(t[0:frmLength],freq,np.transpose(stream_r[0:frmLength,:]), shading='gouraud')
  
  # for i in range(cycles):
  #     # data_wav = wf.readframes(CHUNK)
      
  #     left_spec.set_array(np.transpose(stream_l[i:i+frmLength,:]).ravel())
  #     right_spec.set_array(np.transpose(stream_r[i:i+frmLength,:]).ravel())
      
  #     # left_spec = ax1.pcolormesh(np.transpose(stream_l[i:i+len(frmLength),:]), shading='gouraud')
  #     # right_spec = ax2.pcolormesh(np.transpose(stream_r[i:i+len(frmLength),:]), shading='gouraud')
      
  #     fig.canvas.draw()
  #     fig.canvas.flush_events()
      
  #     # stream.write(data_wav)
  
  def animate(i):
      # data_wav = wf.readframes(CHUNK)
      
      left_spec.set_array(np.transpose(stream_l[i:i+frmLength,:]).ravel())
      right_spec.set_array(np.transpose(stream_r[i:i+frmLength,:]).ravel())
      
      # stream.write(data_wav)
      return left_spec,right_spec
      
  anim = animation.FuncAnimation(fig, animate, interval=10, repeat=False)
  plt.show()
  </code></pre>
  <p>I am running it in Spyder, using Python 3.8. And I did set the graphics backend to automatic.</p>
  <p>Any advice or tips?</p>