Converting midi2wav using fluidsynth

Converting midi to wav using fluidsynth is not entirely trivial. Here is how I do it:

# convert opensolo.mid to fluidsynth.raw using the soundfont /usr/share/sounds/sf2/FluidR3_GM.sf2 
fluidsynth -l -i -a file -z 2048 /usr/share/sounds/sf2/FluidR3_GM.sf2 opensolo.mid
# convert fluidsynth.raw to fluidsynth.wav using sox
sox -b 16 -c 2 -s -r 44100 fluidsynth.raw fluidsynth.wav

You can use this together with the midi export of tuxguitar to export tuxguitar and guitarpro files to wav files.

m-audio Axiom 61 on Linux (Ubuntu 9.10)

I bought myself a M-Audio Axiom 61 to play around with. It works nicely on Linux, plug & play, literally. I tried it with the demo version of Pianoteq and Fluidsynth. Both worked perfectly on the first try. I'm happy so far.

Trick 37: Sniffing http traffic with tcpdump

Sniffing http traffic can be quite useful to find out what's going wrong on a webserver. Here is a simple way to do it using tcpdump:
tcpdump -X tcp port 80

Installing the nvidia opencl driver on ubuntu 9.10

Yesterday, I messed up my system by trying to install a NVIDIA beta driver in order to use opencl. Today I tried again with more success. Here is how I did it:

  1. Download the driver from the NVIDIA website
  2. Open the hardware driver manager of Ubuntu (Sytem/Administration/Hardware Drivers)
  3. Select the NVIDIA accelerated graphics driver (the active one) and click remove
  4. Log out
  5. Press CTRL+ALT+F1 to get to the console
  6. Login with your username and password
  7. sudo stop gdm
  8. chmod +x ./nvdrivers_*.run
  9. sudo ./nvdrivers_*.run
  10. sudo init 6
  11. Enjoy OpenCL goodness

A WORD OF WARNING don't try this unless you understand all the steps involved and know how to recover your system in case something goes wrong!

Stay tuned for some nice opencl experiment.

Autostart/Autorun with Python

Some time ago I wrote a little python module to automatically start programs when a user logs in. It works on Windows and Linux. On windows it creates registry entries, on linux it creates *.desktop files as defined in the Desktop Application Autostart Specification. You can use it like this:
import os
import autorun
autorun.add("myapp", os.path.abspath(__file__))
So here's the code:
#!/usr/bin/env python
"""A simple crossplatform autostart helper"""
from __future__ import with_statement

import os
import sys

if sys.platform == 'win32':
    import _winreg
    _registry = _winreg.ConnectRegistry(None, _winreg.HKEY_CURRENT_USER)
    def get_runonce():
        return _winreg.OpenKey(_registry,
                r"Software\Microsoft\Windows\CurrentVersion\Run", 0,
        _winreg.KEY_ALL_ACCESS)

    def add(name, application):
        """add a new autostart entry"""
        key = get_runonce()
        _winreg.SetValueEx(key, name, 0, _winreg.REG_SZ, application)
        _winreg.CloseKey(key)

    def exists(name):
        """check if an autostart entry exists"""
        key = get_runonce()
        exists = True
        try:
            _winreg.QueryValueEx(key, name)
        except WindowsError:
            exists = False
        _winreg.CloseKey(key)
        return exists

    def remove(name):
        """delete an autostart entry"""
        key = get_runonce()
        _winreg.DeleteValue(key, name)
        _winreg.CloseKey(key)
else:
    _xdg_config_home = os.environ.get("XDG_CONFIG_HOME", "~/.config")
    _xdg_user_autostart = os.path.join(os.path.expanduser(_xdg_config_home),
            "autostart")

    def getfilename(name):
        """get the filename of an autostart (.desktop) file"""
        return os.path.join(_xdg_user_autostart, name + ".desktop")

    def add(name, application):
        """add a new autostart entry"""
        desktop_entry = "[Desktop Entry]\n"\
            "Name=%s\n"\
            "Exec=%s\n"\
            "Type=Application\n"\
            "Terminal=false\n" % (name, application)
        with open(getfilename(name), "w") as f:
            f.write(desktop_entry)

    def exists(name):
        """check if an autostart entry exists"""
        return os.path.exists(getfilename(name))

    def remove(name):
        """delete an autostart entry"""
        os.unlink(getfilename(name))
def test():
    assert not exists("test_xxx")
    try:
        add("test_xxx", "test")
        assert exists("test_xxx")
    finally:
        remove("test_xxx")
    assert not exists("test_xxx")

if __name__ == "__main__":
    test()
I hope that helps somebody. :)

Getting audio to work on a HP Pavilion dv5 / Ubuntu 9.10

It looks like the problem is still there in Ubuntu 9.10, and it looks like the old fix still works. But it looks gorgeous.

Replacing Newlines and Quotes with XSLT

To replace newline and quotes with spaces just use translate(select, "
'", " ");

Example:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"
>
  <xsl:output method="xml" indent="yes"/>
  <xsl:template match="text()">
    <xsl:value-of select='translate(., "&#xA;&apos;", "  ")' />
  </xsl:template>
  <xsl:template match="node">
    <xsl:copy>
      <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>

Generating Maps/Mazes with Python

Last weekend I wrote some code to generate random mazes in python. The algorithm creates fully connected mazes using backtracking. So between two points in the maze there is always exactly one path. In a game you would probably want to remove some more walls to create loops.

#!/usr/bin/env python
import sys
from random import shuffle

def shuffled(x):
    y = list(x)
    shuffle(y)
    return y

DIRECTIONS = (
    (0, -1),
    (0, 1),
    (1, 0),
    (-1, 0),
)

def make_maze(width, height, cellsize):
    cellsize1 = cellsize+1 # cellsize including one wall
    field_width = width*cellsize1+1
    field_height = height*cellsize1+1
    field = [0]*(field_width*field_height)
    stack = [(0, 0, shuffled(DIRECTIONS))]
    while stack:
        x, y, directions = stack[-1]
        dx, dy = directions.pop()
        # no other ways to go from here
        if not directions:
            stack.pop()
        # new cell
        nx = x+dx
        ny = y+dy
        # out of bounds
        if not (0 <= nx < width and 0 <= ny < height):
            continue
        # index of new cell in field
        fx = 1+nx*cellsize1
        fy = 1+ny*cellsize1
        fi = fx+fy*field_width
        # already visited
        if field[fi]:
            continue
        # tear down walls
        if dx > 0:
            a = -1
            b = field_width
        elif dx < 0:
            a = cellsize
            b = field_width
        elif dy > 0:
            a = -field_width
            b = 1
        else:
            a = cellsize*field_width
            b = 1
        for offset in xrange(cellsize):
            field[fi+a+b*offset] = 1
        # clear cell
        for y in xrange(0, cellsize):
            for x in xrange(0, cellsize):
                field[fi+x+y*field_width] = 1
        # visit cell
        stack.append([nx, ny, shuffled(DIRECTIONS)])
    return field

if __name__ == "__main__":
    if len(sys.argv) != 4:
        raise SystemExit("Usage: %s width height cellsize" % sys.argv[0])
    width, height, cellsize = map(int, sys.argv[1:])
    fields = make_maze(width, height, cellsize)
    w = (cellsize+1)*width+1
    h = (cellsize+1)*height+1
    for y in xrange(h):
        print "".join(map(lambda x: x and " " or "#", fields[y*w:y*w+w]))

And here some examples of the output:

#############################################################
#     #           #              #        #           #     #
#     #           #              #        #           #     #
#  ####  ####  #  #  ##########  #  #  #  #  #######  #  ####
#     #  #     #     #           #  #  #     #     #  #     #
#     #  #     #     #           #  #  #     #     #  #     #
####  #  #  ##########  #############  #######  #  #  ####  #
#     #  #  #  #     #     #           #     #  #  #        #
#     #  #  #  #     #     #           #     #  #  #        #
#  #######  #  #  #  ####  #######  ####  ####  #  #######  #
#           #     #  #     #        #  #     #  #        #  #
#           #     #  #     #        #  #     #  #        #  #
#############  ####  #  ####  #######  #  #  #  #  #######  #
#                 #           #           #     #           #
#                 #           #           #     #           #
#############################################################
################
#           #  #
#           #  #
#  #  #  #  #  #
#  #  #  #  #  #
#  #  #  #  #  #
#  ####  #  #  #
#        #     #
#        #     #
#############  #
#     #        #
#     #        #
#  ####  #######
#              #
#              #
################

New Game: JS WARS

Today I release JS WARS to the public. JS WARS is a side scrolling shooter programmed using JavaScript and the html5 canvas/audio elements. All the graphics and sounds were created using free software (blender, gimp and csound). Go check it out! I know you want to!.


How to disable pulseaudio on ubuntu 9.04

PLEASE DO NOT FOLLOW THE INSTRUCTIONS IN THIS POST UNLESS YOU KNOW WHAT YOU ARE DOING.

Pulse audio seems to be a constant source of trouble for me while providing no benefits at all (at least not any noticeable ones). So here's how to get rid of it:

Open /etc/X11/Xsession.d/70pulseaudio in a text editor and comment out everything (put a # in front of every line) and then save it.

This will prevent pulse audio from being started when you log in.