2016년 3월 12일 토요일

Uncompressed audio playback using Python 2 pyglet

Python 2's pyglet module is quite popular for making games as it can render graphics files like png and also playback uncompressed audio. pyglet is not capable of playing compressed audio, however; for this task it has traditionally relied on the avbin plugin. Unfortunately, avbin is not under active development anymore and many programs using pyglet require ancient versions of avbin to be installed on your system.

Take, for instance, the dual N-back training game Brain Workshop (BW). Written in Python 2 and pyglet, it uses both uncompressed wav and compressed ogg audio files. For playing ogg files, BW requires avbin 7, which was released in 2008. This is a problem because most Linux distributions don't provide avbin in their default repositories (and even if they did, they would use the latest version avbin 10/11). In another post, I will describe some changes I made to Brain Workshop's python source to remove the dependency on avbin. The trick is to first convert all compressed audio to wav and then to use pyglet's built-in audio playback function.

When attempting to play wav files with pyglet, you must make sure that there are no audio tags encoded in the file. If any tags exist, pyglet will give a WAVEFormatException complaining that the format is invalid. Let's say you convert ogg to wav using ffmpeg:

$ ffmpeg -i Concert.ogg Concert.wav

A file converted in this way will be tagged with the string Lavf56.40.101 in the field Software:


The screenshot above is from Audacity, an open source digital audio workstation. If you select edit metadata tags from the File menu you will be able to see what information, if any, is encoded as metadata. Clear Lavf56.40.101 and re-export the file to wav (Microsoft PCM, 16 bit) and you should be able to play the file with pyglet:


import pyglet
source = pyglet.media.load('Concert.wav')
source.play()