Un4Seen’s BASS Audio Library is a popular, cross-platform closed-source library for playing and recording audio streams in a number of popular formats. I personally have used it previously within Microsoft .NET. Now it’s possible to use this useful library within Python, thanks to a ctypes module.

You see, BASS is a C Library. The Python interpreter is also commonly compiled for C. Using the ctypes library it’s possible to make these two things work together for good.

What can you do with BASS?

In it’s simplest form, BASS can record and play audio files in formats such as WAV, MP2, MP3, MP1, OGG and AIFF. It supports multiple streams simultaneously, to multiple sound cards (or use the mixer module to play multiple things to the one output device). It also supports many effects such as time stretching (used a lot in radio to make the hours time out correctly), via the BASS FX plug-in.

Getting Started with BASS for Python

Using the full power of BASS and it’s plugins is possible in Python thanks to the PyBASS module. It’s available on GitHub and SourceForge. It’s a ctypes module, which basically means the original C methods are exposed to Python. Here’s how to get started:

  1. Download the module (from a link above – I used the SourceForge version)
  2. Download the main BASS library from their website (there are versions for each platform – choose the correct one)
  3. Add the platform-specific files to the PyBASS directory.
    1. For PC, copy the bass.dll file.
    2. For Mac, copy the libbass.dylib file and rename it to libbass.so
  4. Run one of the sample projects, and use that as a starting point for your own project

For each of the additional modules you use, you’ll need to download the appropriate libraries from the Un4Seen BASS website and copy it into the correct location. It’s important to note that BASS is not open source, and indeed must be paid for for non-personal projects, so check your license compatibility when using this library (especially if you want to embed the compiled libraries in your project).

PyBASS Sample Code

The examples provided by PyBASS are quiet good. As a point of reference, here is a super-simple player. It contains no error-checking or the like. It will either play your audio file or it won’t.

from pybass import *
BASS_Init(-1, 44100, 0, 0, 0)
filePlayerHandle = BASS_StreamCreateFile(False, “mySampleFile.mp3”, 0, 0)
BASS_ChannelPlay(filePlayerHandle, False)

It’s really that simple!

PyBASS and BASS FX Plugin

PyBASS provides wrappers for a lot of BASS ‘extras’ (such as the Mixer module), but not the FX plugin. Thankfully, it’s fairly easy to start adding ctypes FX wrappers yourself if you are a little familiar with Python. I’ve done a little work on this already to implement time stretching. Here is an example, as a GitHub Gist.

'''
This is a simple wrapper for BASS FX in Python, based on PyBASS.
It's incomplete code, but demonstrates basic functionality of the FX plugin in Python.

Feel free to do whatever you like with this. Make it your own.

More info: http://mediarealm.com.au/articles/2014/08/un4seen-bass-audio-library-python/
'''

if platform.system().lower() == 'windows':
	fx_module = ctypes.WinDLL('./libbass_fx.dll')
	fx_func_type = ctypes.WINFUNCTYPE
else:
    fx_module = ctypes.CDLL('./libbass_fx.so')
    fx_func_type = ctypes.CFUNCTYPE


BASS_FX_GetVersion = func_type(ctypes.c_ulong)(('BASS_FX_GetVersion', fx_module))
BASS_FX_BFX_ROTATE = 0x10000
BASS_FX_BFX_ECHO = 0x10001
BASS_FX_BFX_FLANGER = 0x10002
BASS_FX_BFX_VOLUME = 0x10003
BASS_FX_BFX_PEAKEQ = 0x10004
BASS_FX_BFX_MIX = 0x10005
BASS_FX_BFX_DAMP = 0x10006
BASS_FX_BFX_AUTOWAH = 0x10007
BASS_FX_BFX_ECHO2 = 0x10008
BASS_FX_BFX_PHASER = 0x10009
BASS_FX_BFX_CHORUS = 0x10010
BASS_FX_BFX_DISTORTION = 0x10011
BASS_FX_BFX_COMPRESSOR2 = 0x10012
BASS_FX_BFX_VOLUME_ENV = 0x10013
BASS_FX_BFX_BQF = 0x10014
BASS_FX_BFX_ECHO4 = 0x10015

BASS_ATTRIB_TEMPO = 0x10000
BASS_FX_FREESOURCE = 0x10000
BASS_FX_TempoCreate = func_type(HSTREAM, ctypes.c_ulong)(('BASS_FX_TempoCreate', fx_module))

#This must be called for the FX stuff to work:
BASS_FX_GetVersion()


###########################################################
#Below is a example of time stretching in Un4Seen BASS FX

BASS_Init(-1, 44100, 0, 0, 0)

filePlayerHandle = BASS_StreamCreateFile(False, fileName, 0, 0, BASS_STREAM_DECODE)
tempoChannel = BASS_FX_TempoCreate(filePlayerHandle, BASS_FX_FREESOURCE)

BASS_ChannelSetAttribute(tempoChannel, BASS_ATTRIB_TEMPO, 100)

if not BASS_ChannelPlay(tempoChannel, False):
  print('BASS_ChannelPlay error %s' % get_error_description(BASS_ErrorGetCode()))

else:
  print "Started playing..."
  
  

 

Hopefully this has been of some help to you. Although there is not too much information out there about using BASS within a Python application, it is absolutely possible and possibly the best way to handle audio in Python. If there’s anything you would like to add, post it in the comments.

Get the Broadcast Technology Newsletter

Sign up for the email newsletter about media and technology. Sent irregularly. No spam.

I'm Anthony Eden, and I'm a IT Professional, Broadcast Technician, Software Developer, and Solutions Engineer. I've been working in broadcast media since 2008, and developing software and websites for just as long. Right now, I provide freelance services through Media Realm - in particular, to the media and not-for-profit industries.

Follow Anthony on Twitter: @anthony_eden