code: def play(self, wav=None, data=None, rate=16000, channels=1, width=2, block=True, spectrum=None):
          
          if wav:
              f = wave.open(wav, 'rb')
              rate = f.getframerate()
              channels = f.getnchannels()
              width = f.getsampwidth()
  
              def gen(w):
                  d = w.readframes(CHUNK_SIZE)
                  while d:
                      yield d
                      d = w.readframes(CHUNK_SIZE)
                  w.close()
  
              data = gen(f)
  
          self.stop_event.clear()
          if block:
              self._play(data, rate, channels, width, spectrum)
          else:
              thread = threading.Thread(target=self._play, args=(data, rate, channels, width, spectrum))
              thread.start()
docs: play wav file or raw audio (string or generator)
          Args:
              wav: wav file path
              data: raw audio data, str or iterator
              rate: sample rate, only for raw audio
              channels: channel number, only for raw data
              width: raw audio data width, 16 bit is 2, only for raw data
              block: if true, block until audio is played.
              spectrum: if true, use a spectrum analyzer thread to analyze data