ASCIIMath creating images

Wednesday, November 1, 2017

Halloween Raspberry Pi project

Halloween is a great time to do projects if you have kids.  There is a lot of fun to be had building animated things for displays or costumes.  In our case, Madeline and I collaborated on a great costume for our son, who wanted to go as a Robot.  She found some shiny material and sewed it up, and I build an animated control panel.

The Rπ0 controls a IIC-connected OLED display (128x32) and 9 LEDs via the GPIOs. I could theoretically have used an Arduino - but the OLED display is 3.3V only, and I only have 5V Arduinos (I know I can just underclock them, but not during development).  Thickness was also a factor - the Rπ0 is VERY flat.

The panel is built mostly of Moosgummi (craft foam rubber), and I mounted my Raspberry Pi 0 into it.  The Rπ0 and all the other stuff is mounted in a sandwich of Moosgummi sheets with strips of Moosgummi around the edge.  Power and development (eg. changing the scrolling message or the blink pattern) is done trough a gap, through which a (short) USB cable is fed.  The LEDs are connected trough 150 Ohm resistors directly to the GPIOs.

The SD card has Raspbian Stretch Lite on it, to which I added the Adafruit SSD1306 Python library.  The Python script (placed in a Gist here) running the display and the LEDs sits in the (FAT-formatted) boot partition, and is called from rc.local.  Once that was all in place, I used the Read-Only Raspbian script to make the system read-only; this way I can just pull the power once the trick-or-treating is done.  The script on the boot partition can still be edited at will by remounting /boot read-write (or pulling the SD card and editing it on a different computer!)  The Rπ0 acts as a USB Ethernet gadget, and I can just ssh into it.

Life lesson learned: Mounting blinking LEDs on your kids makes them very easy to find at night! Note to self: next time, add lights to the back (of the kids) as well.

Sunday, May 7, 2017

NNResample package on PyPI

In the previous post, I described my filter generation method for scipy.signal.resample_poly, where the filter is designed such that the first null if the filter is on Nyquist.  For easier inclusion into my own projects, I made it into a package as a self-standing function, and then decided to make that my first submission to PyPI.  The package depends only on numpy and scipy>=0.18.0.

So, if you want to use my resampler, you can now simply do `pip install nnresample`. To report bugs, the link to the repository is

I've included one "special feature": since it takes a little time to generate the filter (to search for the null and regenerate the filter afterwards) the generated filter is cached in a global for re-use.

As for the name, since I'm calling it "Null-on-Nyquist Resampler", the obvious name should be non-resample, but I think that could be confusing...

Wednesday, May 3, 2017

Resampling in Python: Electric Bugaloo

In a previous post, I looked at some sample rate conversion methods for Python, at least for audio data.  I did some more digging into it, and thanks to a note by Prof. Christian Muenker from the Munich University of Applied Sciences I was made aware of scipy.signal.resample_poly (new in scipy since 0.18.0).  This lead me down a bit of a rabbit-hole and I ended up with a Jupyter Notebook which I'm not going to copy-paste here since there is quite a bit of code and some LaTeX in there.  Here is the link to it instead.

For the impatient, here are the interesting bits:

def resample_poly_filter(up, down, beta=5.0, L=16001):
    # *** this block STOLEN FROM scipy.signal.resample_poly ***
    # Determine our up and down factors
    # Use a rational approximation to save computation time on really long
    # signals
    g_ = gcd(up, down)
    up //= g_
    down //= g_
    max_rate = max(up, down)

    sfact = np.sqrt(1+(beta/np.pi)**2)
    # generate first filter attempt: with 6dB attenuation at f_c.
    filt = firwin(L, 1/max_rate, window=('kaiser', beta))
    N_FFT = 2**19
    NBINS = N_FFT/2+1
    paddedfilt = np.zeros(N_FFT)
    paddedfilt[:L] = filt
    ffilt = np.fft.rfft(paddedfilt)
    # now find the minimum between f_c and f_c+sqrt(1+(beta/pi)^2)/L
    bot = int(np.floor(NBINS/max_rate))
    top = int(np.ceil(NBINS*(1/max_rate + 2*sfact/L)))
    firstnull = (np.argmin(np.abs(ffilt[bot:top])) + bot)/NBINS
    # generate the proper shifted filter
    filt2 = firwin(L, -firstnull+2/max_rate, window=('kaiser', beta))
    return filt2

wfilt = resample_poly_filter(P, Q, L=2**16+1)
plt.specgram(scipy_signal.resample_poly(sig, P, Q, window=wfilt)*30, scale='dB', Fs=P, NFFT=256)

Recycling my test sweep from the previous post, I get:
Sweep resampled using my own filter
But really, please read the Notebook.  Comments are welcome!

Monday, March 20, 2017

Publication update

This blog has been basically been inactive since last October since being a PostDoc means that there are a whole bunch other things that I am busy with.  And of course, it was winter - that means statistically, there is always someone in the family who is sick (kids bring home every germ that is going around...).

View of Kiel. Source: Johannes Barre 2006, on Wikipedia
But it is spring now!  And I have just returned from DAGA 2017 in Kiel (where we found a very nice Thai restaurant) so time to update some of my work!

First off, my colleagues in Hannover published "Customized high performance low power processor for binaural speaker localization" at ICECS 2016 in Monte Carlo, Monaco (paper on IEEE Xplore), there was the Winter plenary of Hearing4all, and at DAGA 2017, I presented "Pitch features for low-complexity online speaker tracking", and Sarina (Ph.D. student I'm co-supervising) presented "A distance measure to combine monaural and binaural auditory cues for sound source segregation", both of which can be found on my homepage.  In the pipeline is now "Real-time Implementation of a GMM-based Binaural Localization Algorithm on a VLIW-SIMD Processor" by Christopher, which has been accepted and will be presented at ICME 2017 in Hong Kong in July, and I submitted a paper ("Segregation and Linking of Speech Glimpses in Multisource Scenarios on a Hearing Aid") to EUSIPCO 2017; that one is still in review.

I was also teaching a class in the past semester ("5.04.4223 Introduction into Music Information Retrieval") which, because it's a brand new class took a crazy amount of work to prepare for - but I think the students really enjoyed it, and I saw some very good code being written for the final project.

Now back to real work (writing more papers, that is)!  (Well, there's one or two topics I'll put on the blog in the next little while, too.  Later.)

Friday, March 17, 2017

What happened to my homepage? Or: why you should read emails from your hosting provider carefully...

Having had about a million things on my plate recently (WHEN was the last time I blogged anything?), I tend to prioritize emails - and I did kinda ignore an email sent out by Atlassian in January.  It meant to inform me that the personal homepages on BitBucket were moving from to (and switching to https in the process); a redirect from Jan 23rd on, then the old link would be dead after March 1st.

I noticed this of course only when I suddenly couldn't access my homepage. D'Oh!

I have now gone though most of the blog postings here to fix all the links.  If you find any that I missed (or other dead links) please let me know in the comments! Thanks!