[PyOpenGL-Users] Rolling spectrogram with pyopengl
Brought to you by:
mcfletch
From: Timothée L. <tim...@lp...> - 2009-12-03 14:21:50
|
Dear pyopengl users, I am writing (as a hobby) an application that does real-time visualization of audio data. The main widget is a rolling spectrogram, that is a colored image where the horizontal axis is the time, the vertical axis is the frequency, and the color of each pixel represents the intensity of the corresponding spectrum component (see http://www.flickr.com/photos/41584197@N03/3832486029/in/set-72157622072708326/ for example). Each column of the image is computed with a FFT of the audio data every 20 ms or so, and the whole image is displayed on screen and "rolls" and time goes by. I am trying to use OpenGL to improve the performance of the part of the application that displays the image on the screen, but I can't manage to get it really faster than a simple 2D blitting, so I am asking for your help ! Currently, I first set up a texture with the following : # Create Texture GL.glGenTextures(1, self.texture) # generate one texture name GL.glBindTexture(GL.GL_TEXTURE_2D, self.texture) # bind a 2d texture to the generated name GL.glPixelStorei(GL.GL_UNPACK_ALIGNMENT, 1) GL.glTexImage2D(GL.GL_TEXTURE_2D, 0, GL.GL_RGBA, 2*self.canvas_width, height, 0, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE, None) GL.glTexParameterf(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_S, GL.GL_CLAMP) GL.glTexParameterf(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_T, GL.GL_CLAMP) GL.glTexParameterf(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_S, GL.GL_REPEAT) GL.glTexParameterf(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_T, GL.GL_REPEAT) GL.glTexParameterf(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_NEAREST) GL.glTexParameterf(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_NEAREST) GL.glTexEnvf(GL.GL_TEXTURE_ENV, GL.GL_TEXTURE_ENV_MODE, GL.GL_DECAL) Then, every 20 ms or so, I modify two columns of that texture with : GL.glTexSubImage2D(GL.GL_TEXTURE_2D, 0, self.offset, 0, 1, self.height, GL.GL_BGRA, GL.GL_UNSIGNED_BYTE, byteString) GL.glTexSubImage2D(GL.GL_TEXTURE_2D, 0, self.offset + self.canvas_width, 0, 1, self.height, GL.GL_BGRA, GL.GL_UNSIGNED_BYTE, byteString) And I draw part of that texture to my widget with : GL.glLoadIdentity() GL.glBegin(GL.GL_QUADS) xoff = float(self.offset)/(2*self.canvas_width) GL.glTexCoord2f(xoff, 0.) GL.glVertex2f(0, 0) GL.glTexCoord2f(1.+xoff , 0.) GL.glVertex2f(2*self.canvas_width, 0) GL.glTexCoord2f(1.+xoff, 1.) GL.glVertex2f(2*self.canvas_width, self.height) GL.glTexCoord2f(xoff, 1.) GL.glVertex2f(0, self.height) GL.glEnd() Profiling shows that the two GL.glTexSubImage2D take a lot of time (more than twice as much as the whole drawing part) whereas it's "just" two single columns of the texture being updated... What can I do to optimize this ? Is there a smarter way to achieve the same result ? Thanks for your help ! Timothée Lecomte |