WARNING: this project is largely outdated, and some of the modules are no longer supported by modern distributions of Python.
For a more modern, cleaner, and more complete GUI-based viewer of realtime audio data (and the FFT frequency data), check out my Python Real-time Audio Frequency Monitor project.
Consider realtime spectrograph software like QRSS VD. It’s primary function is to scroll a potentially huge data-rich image across the screen. In Python, this is often easier said than done. If you’re not careful, you can tackle this problem inefficiently and get terrible frame rates (<5FPS) or eat a huge amount of system resources (I get complaints often that QRSS VD takes up a lot of processor resources, and 99% of it is drawing the images). In the past, I’ve done it at least 4 different ways (one, two, three, four, five). Note that “four” seems to be the absolute fastest option so far. I’ve been keeping an eye out for a while now contemplating the best way to rapidly draw color-mapped 8-bit data in a python program. Now that I’m doing a majority of my graphical development with PyQt and QtDesigner (packaged with PythonXY), I ended-up with a solution that looks like this (plotting random data with a colormap):
1.) in QtDesigner, create a form with a scrollAreaWidget
2.) in QtDesigner, add a label inside the scrollAreaWidget
3.) in code, resize label and also scrollAreaWidgetContents to fit data (disable “widgetResizable”)
4.) in code, create a QImage from a 2D numpy array (dtype=uint8)
5.) in code, set label pixmap to QtGui.QPixmap.fromImage(QImage)
That’s pretty much it! Here are some highlights of my program. Note that the code for the GUI is in a separate file, and must be downloaded from the ZIP provided at the bottom. Hope it helps someone else out there who might want to do something similar!
import ui_main import sys from PyQt4 import QtCore, QtGui import sys from PyQt4 import Qt import PyQt4.Qwt5 as Qwt from PIL import Image import numpy import time spectroWidth=1000 spectroHeight=1000 a=numpy.random.random(spectroHeight*spectroWidth)*255 a=numpy.reshape(a,(spectroHeight,spectroWidth)) a=numpy.require(a, numpy.uint8, 'C') COLORTABLE= for i in range(256): COLORTABLE.append(QtGui.qRgb(i/4,i,i/2)) def updateData(): global a a=numpy.roll(a,-5) QI=QtGui.QImage(a.data, spectroWidth, spectroHeight, QtGui.QImage.Format_Indexed8) QI.setColorTable(COLORTABLE) uimain.label.setPixmap(QtGui.QPixmap.fromImage(QI)) if __name__ == "__main__": app = QtGui.QApplication(sys.argv) win_main = ui_main.QtGui.QWidget() uimain = ui_main.Ui_win_main() uimain.setupUi(win_main) # SET UP IMAGE uimain.IM = QtGui.QImage(spectroWidth, spectroHeight, QtGui.QImage.Format_Indexed8) uimain.label.setGeometry(QtCore.QRect(0,0,spectroWidth,spectroHeight)) uimain.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0,0,spectroWidth,spectroHeight)) # SET UP RECURRING EVENTS uimain.timer = QtCore.QTimer() uimain.timer.start(.1) win_main.connect(uimain.timer, QtCore.SIGNAL('timeout()'), updateData) ### DISPLAY WINDOWS win_main.show() sys.exit(app.exec_())