Python: PyAudio and PyGst with Gstreamer
Here is an example from the PyAudio docs. We import the audio libraries first and then
sys which enables us to read and write files. Then we do what we've done in every example, which is to set the format of the audio and the audio device. We open a stream, grab the stuff, and then save it.
""" Record a few seconds of audio and save to a WAVE file. """ import pyaudio import wave import sys chunk = 1024 FORMAT = pyaudio.paInt16 CHANNELS = 1 RATE = 44100 RECORD_SECONDS = 5 WAVE_OUTPUT_FILENAME = "output.wav" p = pyaudio.PyAudio() stream = p.open(format = FORMAT, channels = CHANNELS, rate = RATE, input = True, frames_per_buffer = chunk) print "* recording" all =  for i in range(0, RATE / chunk * RECORD_SECONDS): data = stream.read(chunk) all.append(data) print "* done recording" stream.close() p.terminate() # write data to WAVE file data = ''.join(all) wf = wave.open(WAVE_OUTPUT_FILENAME, 'wb') wf.setnchannels(CHANNELS) wf.setsampwidth(p.get_sample_size(FORMAT)) wf.setframerate(RATE) wf.writeframes(data) wf.close()
Note how minimal this code is. There is no GUI, of course, so that helps as well.
A good introduction to Gstreamer is Jono Bacon's article that describes the workings of Gstreamer and the PyGst bindings. Gstreamer offers quite a lot of creative possibilities and, unlike ESD, offers the possibility of having more than one audio stream playing at one time, amongst many other features.
Below is an example of code from the PyGst docs of a simple audio player. We grab the
sys, windowing, and
pygst stuff, set up the window and the player, and away we go. Note that some implementations, particularly for small devices, are missing crucial bits. For example, I was interested to do a command line version for a Nokia 770 to play loops and wasn't able to.
#!/usr/bin/env python import sys, os, os.path import pygtk, gtk, gobject import pygst pygst.require("0.10") import gst class GTK_Main: def __init__(self): window = gtk.Window(gtk.WINDOW_TOPLEVEL) window.set_title("Audio-Player") window.set_default_size(400, 300) window.connect("destroy", gtk.main_quit, "WM destroy") vbox = gtk.VBox() window.add(vbox) self.entry = gtk.Entry() vbox.pack_start(self.entry, False, True) self.button = gtk.Button("Start") self.button.connect("clicked", self.start_stop) vbox.add(self.button) window.show_all() self.player = gst.element_factory_make("playbin", "player") fakesink = gst.element_factory_make('fakesink', "my-fakesink") self.player.set_property("video-sink", fakesink) bus = self.player.get_bus() bus.add_signal_watch() bus.connect('message', self.on_message) def start_stop(self, w): if self.button.get_label() == "Start": filepath = self.entry.get_text() if os.path.exists(filepath): self.button.set_label("Stop") self.player.set_property('uri', "file://" + filepath) self.player.set_state(gst.STATE_PLAYING) else: self.player.set_state(gst.STATE_NULL) self.button.set_label("Start") def on_message(self, bus, message): t = message.type if t == gst.MESSAGE_EOS: self.player.set_state(gst.STATE_NULL) self.button.set_label("Start") elif t == gst.MESSAGE_ERROR: self.player.set_state(gst.STATE_NULL) self.button.set_label("Start") gtk.gdk.threads_init() GTK_Main() gtk.main()
Here we actually have a GUI, but you can see the amount of code needed is still relatively small compared to what would be required with some lower-level language.
Which way you might go to get into Linux Audio depends on what you'd like to achieve. If you're planning to just have some fun while learning something, then wherever you start will be OK. If the fun leads to ideas, then you'll soon figure out whether you need to be deeper into the machine or whether you just need to be sketching on the surface. Just bear in mind that the higher the level you're on, the more you're bound by what other people think about how things should be. This is mostly good in terms of ease and implementation time, but could be bad in terms of constricted horizons.
A good mailing list to join if you get serious is the Linux Audio Dev list, which describes itself like this: "The Linux Audio Developers (LAD) list is dedicated to sound architecture and application development for the Linux Operating System. With its proven stability and scalability, it is a perfect foundation for the handling and processing of large amounts of audio data. Our goal is to encourage widespread code re-use and cooperation, and to provide a common forum for all audio related software projects and an exchange point for a number of other special-interest mailing lists."
At this point, you might say to yourself, well, actually, what I really want to do is make noises or non-standard kinds of music. In that case you could have a look at Csound or Pure Data. You could also look into the synthesis and DSP side of programming, which is something we haven't looked at in this article.
Return to LinuxDevCenter.com.