Adam Obeng

HackNY Spring 2015 Hackathon — And the winner is...

| Categories: hackathon, projects

TL;DR

I won second place at the HackNY Spring 2015 Hackathon with 🐤🎶 (chirp). And I also won first place with GLaPEP8(!) Apparently I'm the first person to win two podium places at a HackNY hackathon.

I've got a post about (chirp), but this is about the HackNY Spring 2015 Hackathon winner:

GLaPEP8

GLaPEP8 is best explained with a demo video:

Demo of GLaPEP8 v0.1 from Adam Obeng on Vimeo.

These are the ChallengePost link and GitHub repo.

GLaPEP8 checks a file's Python syntax and sings the error to you in the style of GLaDOS singing Still Alive in the closing credits of Portal.1 I started building this because I wanted to play around with OS X2's speech synthesis. I'd guess a fair proportion of Mac users know that you can use the command 'say' thus:

say "Arbitrary text"

But the speech synthesis engine in OS X is actually really quite sophisticated and controllable. The interesting thing for our purposes is that you can include commands in the text which let you control various aspects of the synthesised voice, including prosody and tone. I've messed around with this before for livecoding purposes, but I didn't really grok the TUNE format, which gives you the most control — and, as it turns out, I needed very fine-grained control for GLaPEP8.

Basically, you can provide 'say' with a list of syllables, and for each of them specify how long to say it for, and at which frequency. The format is called 'TUNE', and looks like this:

[[ inpt TUNE ]]
~
M {D 60; P 246.00:0}
EH {D 360; P 246.00:0}
r {D 60; P 220.0:0}
IY {D 360; P 220.0:0}
,
h {D 60; P 196.0:0}
AE {D 360; P 196.0:0}
d {D 60; P 196.0:0}
,
UX {D 360; P 220.0:0}
,
l {D 120; P 246.0:0}
IH {D 360; P 246.0:0}
t {D 120; P 246.0:0}
UX {D 120; P 246.0:0}
l {D 120; P 246.0:0}
,
l {D 120; P 246.0:0}
AE {D 480; P 246.0:0}
m {D 60; P 246.0:0}
.

I only need a subset of the features for GLaPEP8, so the only things I'll change are the syllables, the number after 'D' (the duration in ms), and the number after 'P' (the pitch at time 0 of the syllable).

Supplying individual syllables is not super convenient, so I started off trying to use the standard 'TEXT' input format. In that mode, you can also specify the pitch like so:

say '[[ pbas 69 ]] [[ pmod 0 ]] The A above middle C'

'69' is the MIDI number of the frequency you want, and '[[ pmod 0]]' makes the pronunciation monotone. I couldn't use this for GLaPEP8 because there's no way of specifying how long it should take to say a word, so they sound rhythmically weird. You can specify the rate in words-per-minute, but to convert that a note duration in milliseconds to a rate you also need to know in advance how long it would take to say the word!

The problem with providing a syllable-level pronunciation guide is that OS X Speech Synthesis uses a phoneme list which is, as far as I can tell, a non-standard version of Arpabet. I'm converting words to the component phonemes of their pronunciations using CMUdict (the Carnegie Mellon Pronouncing Dictionary), which does use Arpabet, so GLaPEP8 ends up converting words to Arpabet phonemes, then to OS X-style phonemes, then to audio.

The vast majority of the work went into getting OS X to sing like Ellen McLain, but I also used flake8 to find the PEP8 violations in the code, python-midi to read in the melody and the python ncurses library to make an interface like Portal's end credits. For a little bit more 2010-retro-futuristic chic, I demoed GLaPEP8 inside the vintage terminal emulator Cathode.

I started work on GLaPEP8 quite late, and I realised it might actually be worth finishing even later. There are consequently some very rough edges I'd like to fix, such as:

I think I'm going to spin off the text-to-song part of GLaPEP8 into its own project, because I can see myself re-using that (notably for livecoding). I also remain interested in error messages -- to the extent that my PhD dissertation is going to spend quite some time on them, albeit in a slightly more academic context.


  1. Spoiler warning, I guess, for anyone who hasn't played Portal in the 8 years since it was released. 

  2. Sorry other-OS folks, this one only runs on OS X.