PyOracle Demo #1

PyOracle is a project using Python to analyze aspects of musical structure. Audio Oracle, an algorithm based on the Factor Oracle string matching algorithm, is used to detect introductions and repetitions of musical materials. Through this analysis, aspects of musical structure can be understood, and new versions of the analyzed work can be created.

This demonstration uses PyOracle embedded in a Max/MSP patch to perform real-time machine improvisation on an input signal.

Comparing Numba and Numpy

Comparing Numba and Numpy

Greg Surges

surgesg at gmail dot com

http://www.gregsurges.com

After catching Travis Oliphant's Numba talk at PyCon 2013 last week, I thought I'd test Numba out for myself. According to the docs, which can be found at numba.pydata.org, "Numba compiles Python code with LLVM to code which can be natively executed at runtime." So, this is supposed to give Python some siginificant speed increases, and all you have to do is decorate your functions with @jit or @autojit. Cool.

Since I'm doing my DSP work in Python, the task I've decided to test on is a simple FIR low-pass filter of Gaussian-distributed white noise.

I've decided to test in a couple of ways:

  • First, I'm writing a dumb, for-loop style filter routine, without using any Numpy arrays and building my output list element by element. I'm computing the difference equation for the filter directly.
  • Second, I've used a more array-friendly, Numpy style filter method, and the lfilter() function. I expect this to be faster.
In [58]:
from numba import autojit # import numba's autojit decorator
from scipy.signal import lfilter # we'll need this for our filter 
import profile

Here, I'm generating the random noise. 10 seconds of it.

In [74]:
fs = 44100
dur = 10
noise = array(randn(dur * fs, 1), dtype=float32)
plot(noise[0:44100])
xlim((0, 44100))
Out[74]:
(0, 44100)

Now that I have my noise, I need to define my filter coefficients.

My filter has a transfer function a little something like this:

$$ H(z) = \frac{b_0 + b_1z^{-1}}{1} $$

and my $b$ coefficients are $b = [1, 1]$.

In [9]:
# coefficients for simple lowpass FIR
b = [1, 1]
a = 1

I define my functions below. They're commented to help you see which is which.

In [75]:
# basic, stupid, iterative difference-equation method
def apply_filter_d(b, a, x):
    y = []
    x_n1 = double(0.0)
    for i in range(len(x)):
        y.append(b[0] * x[i] + b[1] *x_n1)
        x_n1 = x[i]
    return y

# basic, stupid, iterative difference-equation method, but using Numba
@autojit
def apply_filter_d2(b, a, x):
    y = []
    x_n1 = double(0.0)
    for i in range(len(x)):
        y.append(b[0] * x[i] + b[1] *x_n1)
        x_n1 = x[i]
    return y

# smarter, array-based Numpy method
def apply_filter(b, a, x):
    y = lfilter(b, a, x)
    return y

# smarter, array-based Numpy method, using Numba
@autojit
def apply_filter2(b, a, x):
    y = lfilter(b, a, x)
    return y

So, now using the profile module, let's try these out and see what kind of results we get.

Note that if you're running this on your own, the Numba functions run slower the first time you call them - that's the compilation step happening. They'll run faster after that initial call. Note that I had to remove most of the output from

In [76]:
# iterative method w/o Numba
profile.run('apply_filter_d(b, a, noise)')
         441005 function calls in 11.359 seconds...

In [78]:
# iterative method with Numba
profile.run('apply_filter_d2(b, a, noise)')
         2 function calls in 8.110 seconds...

In [79]:
# Numpy method w/o Numba
profile.run('apply_filter(b, a, noise)')
         7 function calls in 0.154 seconds...

In [81]:
# Numpy method with Numba
profile.run('apply_filter2(b, a, noise)')
         6 function calls in 0.138 seconds...

So, to collect the results:

  • Iterative w/o Numba: 11.359s
  • Iterative w/ Numba: 8.110s
  • Array-based w/o Numba: 0.154s
  • Array-based w/ Numba: 0.138

In the iterative functions, the Numba-compiled code ran in 71% of the time of the non-Numba code. In the array-based functions, the Numba code ran in 90% of the time of the non-Numba code.

There are probably ways to better optimize these examples to better exploit what Numba can do, but this shows some definite potential.

In [106]:
ax = figure()
ax = ax.add_subplot(1, 1, 1)
b = ax.bar((0, 0.25, 0.5, 0.75), (11.359, 8.11, 0.154, 0.138), width=(0.1, 0.1, 0.1, 0.1), color=('r', 'g', 'b', 'y'))
ax.set_xticks((0, 0.25, 0.5, 0.75))
ax.set_xticklabels(('IT1', 'IT2', 'AR1', 'AR2'))
grid()
tight_layout()
legend(b, ['Iterative (no Numba)', 'Iterative (Numba)', 'Array (no Numba)', 'Array (Numba)'])
title('Results')
Out[106]:
<matplotlib.text.Text at 0x14319edd0>

PyCon 2013 Poster

The poster on PyOracle I gave at PyCon 2013 is online here.

PyCon was great, and I had fun being an unofficial computer music representative.

 

PyOracle Notebook

Here’s the IPython Notebook I used to demonstrate PyOracle in the 270D graduate computer music seminar at UCSD.

http://nbviewer.ipython.org/urls/bitbucket.org/pucktronix/pyoracle/raw/d046b2bcf473503fa356094cfe4cff774d1aaefc/270D.ipynb

Some of the linked files may not work, but they’re the same as those in this post.

Some PyOracle Recombinations

Here are some recombinations of existing music made using my PyOracle Python module. PyOracle performs an Audio Oracle analysis, which determines connections and repetitions between segments of audio. For more info, you can check out the page here.

Here’s the Oracle structure for the Bach solo cello work used below:

bach-oracle

Each arc in the image indicates similarity between two segments of audio. The similarities make it possible to jump along an arc, rather than continuing linearly, and create a new ordering of the musical material – while maintaining smooth transitions between segments. During recombination, the algorithm walks through this oracle structure, and occasionally jumps either forward or backward along an arc.

Each file indicates a jump number, which gives a probability that, at a given point, playback will jump along an oracle transition rather than continue in a linear fashion. As the percentage increases, the output will consist of increasingly longer segments of the input.

Bach – 40%

Bach – 60%

Bach – 65%

Bach – 85%

Bach – 95%

USB-Octomod

Running a fundraiser for an improved USB-Octomod here: https://tindie.com/shops/pucktronix/usb-octomod-1/

There’s still about a week left to get one.

pyoracle transition matrix

Here’s a transition matrix from a pyoracle analysis of a solo piano work. I’ll be giving a poster on my pyoracle Python module at PyCon 2013 in March. More to come…

image

pyoracle visualization of prokofiev ‘visions fugitives’ no. 1

output

Stuff I heard in 2012

Here are some recordings I enjoyed this year:

David Tudor – Getty Archives.

The Getty Research Library, in Los Angeles, holds David Tudor’s papers and audio/video archives. This year, the recordings of his performances were made open-access. There’s about 4.25 GB of music to be heard, including a bunch of rehearsals and unreleased compositions. The most significant aspect of the performances for me was the realization that the officially released recordings are often truncations of much longer, evening-length works.

 

 

 

Roland Kayn – Simultan

Roland Kayn, who died in 2011, was a composer of electroacoustic music. Kayn was significantly influenced by cybernetics, the science of self-regulating systems. Due to this inspiration, his music was composed using analog synthesis systems and feedback. Kayn attempted to create electronic music systems which would be self-regulating.

Though I listened to most of Kayn’s output this year, I’ve selected his 5-room installation piece Simultan here. It’s available from the Avant-Garde Project as a free download, and is a good first listen.

 

Greg Davis – States Series

 

I spent some time this year listening to Greg Davis’ States series. States is a 4-cassette, 6-part series of modular synth compositions composed and released in 2011. Gradually shifting patterns, raw electronic timbres, great cover art. Unfortunately, the original release was only on cassette, and on a few different labels. However, Davis has recently put much/all of his music, including these releases, on Bandcamp as downloads.

Here’s a Tiny Mix Tapes review of States (3).

 

 

 

John Martyn - London Conversation

Hannah and I spent some time late this year listening to John Martyn’s first two albums. Like a combination of Nick Drake and David Gilmour, with a touch of English whimsy, his music hit the spot for both of us. Beautiful finger-picked guitar and rough-edged vocals.

We had this on repeat basically all Thanksgiving day and it never really got old.

 

New tabulaRasa Fundraiser

The next batch of tabulaRasa pcb/IC sets will be made available a bit differently.

I’m running a small ‘fundraiser’ on Tindie, similar to a Kickstarter. The batch will only be produced if enough people are interested.

Get a tabulaRasa on Tindie!