The Fugue

Counterpoint by Hans Fugal

IMMS

Posted by Hans Fugal Fri, 19 Sep 2008 22:24:00 GMT

So Apple added this Genius thing to iTunes recently. Not being the type to get excited about new iPod styles, it looks like the most interesting thing they could come up with this year. I gave it a try. I am not impressed.

I think it's because I've been spoiled. 5 years ago I was using what I still consider to be the peak of intelligent listening software, IMMS. Genius isn't half as cool as IMMS was then, and while IMMS hasn't made any quantum leaps in coolness, quite a few rough edges have been rounded off in the meantime.

I've been living in a sort of IMMS drought the past couple of years, since I switched to using a laptop primarily. Namely, an Apple laptop. This Genius release spurred me on to rectify that situation. If the best Apple could do was generate a 25-song playlist based on statistics gathered from other people the hopes of someone else hacking up an iTunes plugin to do IMMS or something like it dwindled to obscurity.

The bane of IMMS is, ironically, its most compelling feature. IMMS is cool because you don't have to do anything. It pays attention to your listening habits, and analyzes the audio, and makes intelligent decisions for you when you turn on random. 4 years ago I would show up to work and be in a Depeche Mode mood, so I'd manually queue up a Depeche Mode song or two and the whole day I'd be treated to complementary music. If the occasional happy song slipped through, I just skipped it and IMMS took the hint. Don't underestimate the amazing wow factor of a computer apparently reading your mind.

But this focus on simple non-obtrusive UI has been its biggest technical struggle. Media players are now a dime a dozen, and few of them have the plugin and UI sophistication to support IMMS' modus operandi. IMMS was developed originally as a plugin for XMMS and even then ugly workaround hacks were required. Then someone wrote a queue control patch for XMMS, and if you patched your XMMS you were in heaven. Oh, did I mention that still almost no other media players even have queue functionality, let alone let the plugins control the queue? Then when you consider the set of media players usable on OS X the situation gets laughable.

Somewhere in the middle MPD came along. It fit my situation well because the speakers over on the desktop were a lot nicer than the ones in my laptop. But queues it has not and nobody seems to care. Von bravely came up with an IMMS hack for MPD, but it was too hacky for me—too much like the old XMMS days before the queue control patch (incidentally, queue control is part of XMMS proper now as of version 1.2.11).

So I suffered along with manual or truly random music listening. Until now.

Recently I looked into this again for the desktop, and I was delighted to discover that one of the many XMMS descendants has finally solved the XMMS bitrot without throwing the baby out with the bathwater. Audacious is as cool as XMMS ever was and as modern as your favorite modern player (unless you measure modern by klunky iTunes-like screen-wasting music browsers). What's more, the imms plugin for it is right there in the Ubuntu repository. Just apt-get install imms-audacious and enable the plugin and you're off and running. So I set it up and… didn't use it. As in, we rarely listen to music on the desktop because nobody really sits there for very long. So finally earlier this week I hammered out a simple remote control using Audacious' dbus interface. That's another post, once I knock off a few other TODO points.

Feeling on a roll and feeling left out when at school, I decided to get an IMMS solution on my laptop, running OS X Leopard (10.5.4). I'll spare you the agonizing play-by-play and give you the shortest path to success: install Audacious and then IMMS. Actually the really shortest path is to install XMMS and then IMMS, because XMMS is in MacPorts. But it's the old version of XMMS without queue control, and doesn't have CoreAudio support (you have to use the JACK output plugin) so I don't recommend that.

To install Audacious, install its dependencies (mostly using MacPorts), then build it and its plugins. Installing its dependencies is the hardest part because it's difficult to locate libmcs and libmowgli (they're not where the README says they are, and Google is less than helpful). I just ended up stealing the *.orig.tar.gz files from the Ubuntu packages (apt-get source -d libmcs1 libmowgli). There is one patch you need for the plugins.

 src/CoreAudio/audio.c |    7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

Index: audacious-plugins-1.5.1/src/CoreAudio/audio.c
===================================================================
--- audacious-plugins-1.5.1.orig/src/CoreAudio/audio.c  2008-09-19 12:08:01.000000000 -0600
+++ audacious-plugins-1.5.1/src/CoreAudio/audio.c   2008-09-19 12:10:28.000000000 -0600
@@ -326,7 +326,12 @@ gint osx_get_output_time(void)
 {
        gint retval;

-        retval = output_time_offset + ((output_total * sample_size * 1000) / output.bps);
+        if (output.bps == 0)
+        {
+            printf("Avoiding divide by zero in osx_get_output_time()\n");
+            retval = 0;
+        } else
+            retval = output_time_offset + ((output_total * sample_size * 1000) / output.bps);
        retval = (int)((float)retval / user_pitch);

        //printf("osx_get_output_time(): time is %d\n",retval);

Next you need to install IMMS. This is a bit more involved, but should be straightforward with these patches. I'll put them here and talk about each in turn.

First, a missing include for mkdir()

 immsd/immsd.cc |    1 +
 1 file changed, 1 insertion(+)

Index: imms-3.1.0-rc4/immsd/immsd.cc
===================================================================
--- imms-3.1.0-rc4.orig/immsd/immsd.cc  2008-03-02 18:54:06.000000000 -0700
+++ imms-3.1.0-rc4/immsd/immsd.cc   2008-09-19 08:05:58.000000000 -0600
@@ -2,6 +2,7 @@
 #include <errno.h>
 #include <signal.h>
 #include <unistd.h>
+#include <sys/stat.h>

 #include <iostream>
 #include <sstream>

Then, a workaround due to OS X not having an initstate_r() (which I incidentally couldn't find in the current Linux manpages on Ubuntu or Debian either). This patch may not apply cleanly by itself, you may need to apply your cognitive reasoning.

configure.ac         |    3 +++
immsconf.h           |    3 +++
immsconf.h.in        |    3 +++
immscore/immsutil.cc |    9 +++++++++
4 files changed, 18 insertions(+)

Index: imms-3.1.0-rc4/immscore/immsutil.cc
===================================================================
--- imms-3.1.0-rc4.orig/immscore/immsutil.cc    2008-03-02 18:54:06.000000000 -0700
+++ imms-3.1.0-rc4/immscore/immsutil.cc 2008-09-19 08:13:29.000000000 -0600
@@ -27,6 +27,7 @@ int imms_random(int max)
{
    int rand_num;
    static bool initialized = false;
+#ifndef INITSTATE_BUG
    static struct random_data rand_data;
    static char rand_state[256];
    if (!initialized)
@@ -36,6 +37,14 @@ int imms_random(int max)
        initialized = true;
    }
    random_r(&rand_data, &rand_num);
+#else
+    if (!initialized)
+    {
+        srandom(time(0));
+        initialized = true;
+    }
+    rand_num = random();
+#endif
    double cof = rand_num / (RAND_MAX + 1.0);
    return (int)(max * cof);
}
Index: imms-3.1.0-rc4/configure.ac
===================================================================
--- imms-3.1.0-rc4.orig/configure.ac    2008-03-02 18:54:06.000000000 -0700
+++ imms-3.1.0-rc4/configure.ac 2008-09-19 08:17:58.000000000 -0600
@@ -68,6 +68,9 @@ else
    AC_MSG_RESULT([yes])
fi

+AC_DEFINE(INITSTATE_BUG,, [initstate_r is buggy])
+
+
AC_CHECK_LIB(z, compress,, [with_zlib=no])
AC_CHECK_HEADERS(zlib.h,, [with_zlib=no])
if test "$with_zlib" = "no"; then
Index: imms-3.1.0-rc4/immsconf.h
===================================================================
--- imms-3.1.0-rc4.orig/immsconf.h  2008-09-19 08:05:31.000000000 -0600
+++ imms-3.1.0-rc4/immsconf.h   2008-09-19 08:18:23.000000000 -0600
@@ -121,6 +121,9 @@
/* Define to 1 if you have the <zlib.h> header file. */
#define HAVE_ZLIB_H 1

+/* initstate_r is buggy */
+#define INITSTATE_BUG /**/
+
/* Define to the address where bug reports for this package should be sent. */
#define PACKAGE_BUGREPORT "mag@luminal.org"

Index: imms-3.1.0-rc4/immsconf.h.in
===================================================================
--- imms-3.1.0-rc4.orig/immsconf.h.in   2008-09-19 07:48:52.000000000 -0600
+++ imms-3.1.0-rc4/immsconf.h.in    2008-09-19 08:16:32.000000000 -0600
@@ -120,6 +120,9 @@
/* Define to 1 if you have the <zlib.h> header file. */
#undef HAVE_ZLIB_H

+/* initstate_r is buggy */
+#undef INITSTATE_BUG
+
/* Define to the address where bug reports for this package should be sent. */
#undef PACKAGE_BUGREPORT

This patch is just so libpcre can be found

build/Makefile |    1 +
1 file changed, 1 insertion(+)

Index: imms-3.1.0-rc4/build/Makefile
===================================================================
--- imms-3.1.0-rc4.orig/build/Makefile  2008-03-02 18:54:06.000000000 -0700
+++ imms-3.1.0-rc4/build/Makefile   2008-09-19 12:25:05.000000000 -0600
@@ -18,6 +18,7 @@ libimmscore.a: $(call objects,../immscor
libmodel.a: $(call objects,../model) svm-similarity-data.o
        $(AR) $(ARFLAGS) $@ $(filter %.o,$^)

+immstool-LIBS=`pcre-config --libs`
immstool: immstool.o libmodel.a libimmscore.a 
training_data: training_data.o libmodel.a libimmscore.a 
train_model: train_model.o libmodel.a libimmscore.a

Linking shared libraries on OS X is so much different from on Linux that there is almost always a need to do a patch something like this.

rules.mk |    5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)

Index: imms-3.1.0-rc4/rules.mk
===================================================================
--- imms-3.1.0-rc4.orig/rules.mk    2008-09-19 09:04:13.000000000 -0600
+++ imms-3.1.0-rc4/rules.mk 2008-09-19 12:25:50.000000000 -0600
@@ -14,9 +14,8 @@ link = $(CXX) $(filter-out %.a,$1) $(fil
%.o: %.c; $(call compile, $(CC), $<, $@, $($*-CFLAGS) $(CFLAGS) $($*-CPPFLAGS) $(CPPFLAGS))
%: %.o; $(call link, $^ $($*-OBJ) $(LIBS), $@, $($*-LIBS) $(LDFLAGS))
%.so:
-   $(CXX) $^ $($*-OBJ) $($*-LIBS) $(LIBS) \
-       $(LDFLAGS) \
-            -shared -Wl,-z,defs,-soname,$@ -o $@
+   gcc -flat_namespace -undefined suppress -o $@ -bundle $^ $($*-OBJ) $($*-LIBS) $(LIBS) \
+       $(LDFLAGS) -o $@

%-data.o: %
        $(OBJCOPY) -I binary -O $(OBJCOPYTARGET) -B $(OBJCOPYARCH) --rename-section .data=.rodata,alloc,load,readonly,data,contents $< $@

This final patch fixes IMMS to use the proper interface for audacious (seems like this would have to be done anywhere?)

clients/audacious/audaciousinterface.c |  177 +++++++++++++++++++++++++++++++++
clients/audacious/rules.mk             |    2 
2 files changed, 178 insertions(+), 1 deletion(-)

Index: imms-3.1.0-rc4/clients/audacious/audaciousinterface.c
===================================================================
--- /dev/null   1970-01-01 00:00:00.000000000 +0000
+++ imms-3.1.0-rc4/clients/audacious/audaciousinterface.c   2008-09-19 15:30:21.000000000 -0600
@@ -0,0 +1,177 @@
+#include <gtk/gtk.h>
+
+#ifdef BMP
+#include <bmp/configdb.h>
+#include <bmp/util.h>
+#include <bmp/plugin.h>
+#elif AUDACIOUS
+#include <audacious/configdb.h>
+#include <audacious/util.h>
+#include <audacious/plugin.h>
+#endif
+#include "immsconf.h"
+#include "cplugin.h"
+
+
+int use_xidle = 1;
+int poll_tag = 0;
+
+GtkWidget *configure_win = NULL, *about_win = NULL, *xidle_button = NULL;
+
+gint poll_func(gpointer unused)
+{
+    imms_poll();
+    return TRUE;
+}
+
+void read_config(void)
+{
+    ConfigDb *cfgfile;
+
+    if ((cfgfile = cfg_db_open()) != NULL)
+    {
+        cfg_db_get_int(cfgfile, "imms", "xidle", &use_xidle);
+        cfg_db_close(cfgfile);
+    }
+}
+
+void init(void)
+{
+    imms_init();
+    read_config();
+    imms_setup(use_xidle);
+    poll_tag = gtk_timeout_add(200, poll_func, NULL);
+}
+
+void cleanup(void)
+{
+    imms_cleanup();
+
+    if (poll_tag)
+        gtk_timeout_remove(poll_tag);
+
+    poll_tag = 0;
+}
+
+void configure_ok_cb(gpointer data)
+{
+    ConfigDb *cfgfile = cfg_db_open();
+
+    use_xidle = !!GTK_TOGGLE_BUTTON(xidle_button)->active;
+
+    cfg_db_set_int(cfgfile, "imms", "xidle", use_xidle);
+    cfg_db_close(cfgfile);
+
+    imms_setup(use_xidle);
+    gtk_widget_destroy(configure_win);
+}  
+
+#define ADD_CONFIG_CHECKBOX(pref, title, label, descr)                          \
+    pref##_frame = gtk_frame_new(title);                                        \
+    gtk_box_pack_start(GTK_BOX(configure_vbox), pref##_frame, FALSE, FALSE, 0); \
+    pref##_vbox = gtk_vbox_new(FALSE, 10);                                      \
+    gtk_container_set_border_width(GTK_CONTAINER(pref##_vbox), 5);              \
+    gtk_container_add(GTK_CONTAINER(pref##_frame), pref##_vbox);                \
+                                                                                \
+    pref##_desc = gtk_label_new(label);                                         \
+                                                                                \
+    gtk_label_set_line_wrap(GTK_LABEL(pref##_desc), TRUE);                      \
+    gtk_label_set_justify(GTK_LABEL(pref##_desc), GTK_JUSTIFY_LEFT);            \
+    gtk_misc_set_alignment(GTK_MISC(pref##_desc), 0, 0.5);                      \
+    gtk_box_pack_start(GTK_BOX(pref##_vbox), pref##_desc, FALSE, FALSE, 0);     \
+    gtk_widget_show(pref##_desc);                                               \
+                                                                                \
+    pref##_hbox = gtk_hbox_new(FALSE, 5);                                       \
+    gtk_box_pack_start(GTK_BOX(pref##_vbox), pref##_hbox, FALSE, FALSE, 0);     \
+                                                                                \
+    pref##_button = gtk_check_button_new_with_label(descr);                     \
+    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(pref##_button), use_##pref); \
+    gtk_box_pack_start(GTK_BOX(pref##_hbox), pref##_button, FALSE, FALSE, 0);   \
+                                                                                \
+    gtk_widget_show(pref##_frame);                                              \
+    gtk_widget_show(pref##_vbox);                                               \
+    gtk_widget_show(pref##_button);                                             \
+    gtk_widget_show(pref##_hbox);
+
+void configure(void)
+{
+    GtkWidget *configure_vbox;
+    GtkWidget *xidle_hbox, *xidle_vbox, *xidle_frame, *xidle_desc; 
+    GtkWidget *configure_bbox, *configure_ok, *configure_cancel;
+
+    if (configure_win)
+        return;
+
+    read_config();
+
+    configure_win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+    gtk_signal_connect(GTK_OBJECT(configure_win), "destroy",
+            GTK_SIGNAL_FUNC(gtk_widget_destroyed), &configure_win);
+    gtk_window_set_title(GTK_WINDOW(configure_win), "IMMS Configuration");
+
+    gtk_container_set_border_width(GTK_CONTAINER(configure_win), 10);
+
+    configure_vbox = gtk_vbox_new(FALSE, 10);
+    gtk_container_add(GTK_CONTAINER(configure_win), configure_vbox);
+
+    ADD_CONFIG_CHECKBOX(xidle, "Idleness", 
+#ifdef BMP
+            "Disable this option if you use BEEP on a dedicated machine",
+#elif AUDACIOUS
+            "Disable this option if you use Audacious on a dedicated machine",
+#endif
+            "Use X idleness statistics");
+
+    /* Buttons */
+    configure_bbox = gtk_hbutton_box_new();
+    gtk_button_box_set_layout(GTK_BUTTON_BOX(configure_bbox), GTK_BUTTONBOX_END);
+    gtk_button_box_set_spacing(GTK_BUTTON_BOX(configure_bbox), 5);
+    gtk_box_pack_start(GTK_BOX(configure_vbox), configure_bbox, FALSE, FALSE, 0);
+
+    configure_ok = gtk_button_new_with_label("Ok");
+    gtk_signal_connect(GTK_OBJECT(configure_ok), "clicked",
+            GTK_SIGNAL_FUNC(configure_ok_cb), NULL);
+    GTK_WIDGET_SET_FLAGS(configure_ok, GTK_CAN_DEFAULT);
+    gtk_box_pack_start(GTK_BOX(configure_bbox), configure_ok, TRUE, TRUE, 0);
+    gtk_widget_show(configure_ok);
+    gtk_widget_grab_default(configure_ok);
+
+    configure_cancel = gtk_button_new_with_label("Cancel");
+    gtk_signal_connect_object(GTK_OBJECT(configure_cancel), "clicked",
+            GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(configure_win));
+    GTK_WIDGET_SET_FLAGS(configure_cancel, GTK_CAN_DEFAULT);
+    gtk_box_pack_start(GTK_BOX(configure_bbox), configure_cancel, TRUE, TRUE, 0);
+    gtk_widget_show(configure_cancel);
+    gtk_widget_show(configure_bbox);
+    gtk_widget_show(configure_vbox);
+    gtk_widget_show(configure_win);
+}
+
+void about(void)
+{
+    if (about_win)
+        return;
+
+    about_win =
+#ifdef AUDACIOUS
+        audacious_info_dialog(
+#else
+        xmms_show_message(
+#endif
+            "About IMMS",
+            PACKAGE_STRING "\n\n"
+            "Intelligent Multimedia Management System" "\n\n"
+            "IMMS is an intelligent playlist plug-in for BPM" "\n"
+            "that tracks your listening patterns" "\n"
+            "and dynamically adapts to your taste." "\n\n"
+            "It is incredibly unobtrusive and easy to use" "\n"
+            "as it requires no direct user interaction." "\n\n"
+            "For more information please visit" "\n"
+            "http://www.luminal.org/wiki/index.php/IMMS" "\n\n"
+            "Written by" "\n"
+            "Michael \"mag\" Grigoriev <mag@luminal.org>",
+            "Dismiss", FALSE, NULL, NULL);
+
+    gtk_signal_connect(GTK_OBJECT(about_win), "destroy",
+            GTK_SIGNAL_FUNC(gtk_widget_destroyed), &about_win);
+}
Index: imms-3.1.0-rc4/clients/audacious/rules.mk
===================================================================
--- imms-3.1.0-rc4.orig/clients/audacious/rules.mk  2008-03-02 18:54:06.000000000 -0700
+++ imms-3.1.0-rc4/clients/audacious/rules.mk   2008-09-19 15:28:17.000000000 -0600
@@ -7,7 +7,7 @@ libaudaciousimms-LIBS = $(AUDACIOUSLDFLA
audaciousinterface-CPPFLAGS=$(AUDACIOUSCPPFLAGS)
audplugin-CPPFLAGS=$(AUDACIOUSCPPFLAGS)

-audaciousinterface.o: bmpinterface.c
+audaciousinterface.o: audaciousinterface.c
        $(call compile, $(CC), $<, $@, $($*-CFLAGS) $(CFLAGS) $($*-CPPFLAGS) $(CPPFLAGS))

AUDACIOUSDESTDIR=""

Phew. And that's not all. When you build IMMS you need to have OBJDUMP=gobjdump if you're using the default binutils variant from MacPorts, and this patch:

 rules.mk   |    2 +-
 vars.mk    |    6 +++---
 vars.mk.in |    1 +
 3 files changed, 5 insertions(+), 4 deletions(-)

Index: imms-3.1.0-rc4/rules.mk
===================================================================
--- imms-3.1.0-rc4.orig/rules.mk        2008-09-19 08:49:43.000000000 -0600
+++ imms-3.1.0-rc4/rules.mk     2008-09-19 16:17:33.000000000 -0600
@@ -19,7 +19,7 @@ link = $(CXX) $(filter-out %.a,$1) $(fil
             -shared -Wl,-z,defs,-soname,$@ -o $@

 %-data.o: %
-       objcopy -I binary -O $(OBJCOPYTARGET) -B $(OBJCOPYARCH) --rename-section .data=.rodata,alloc,load,readonly,data,contents $< $@
+       $(OBJCOPY) -I binary -O $(OBJCOPYTARGET) -B $(OBJCOPYARCH) --rename-section .data=.rodata,alloc,load,readonly,data,contents $< $@

 # macros that expand to the object files in the given directories
 objects=$(sort $(notdir $(foreach type,c cc,$(call objects_$(type),$1))))
Index: imms-3.1.0-rc4/vars.mk
===================================================================
--- imms-3.1.0-rc4.orig/vars.mk 2008-09-19 09:03:05.000000000 -0600
+++ imms-3.1.0-rc4/vars.mk      2008-09-19 15:07:44.000000000 -0600
@@ -5,8 +5,8 @@ INSTALL = /opt/local/bin/ginstall -c
 prefix = /usr
 PREFIX = $(prefix)
 OBJCOPY = gobjcopy
-OBJCOPYTARGET = 
-OBJCOPYARCH = 
+OBJCOPYTARGET = mach-o-le
+OBJCOPYARCH = i386
 exec_prefix = ${prefix}
 bindir = ${exec_prefix}/bin
 datadir = ${prefix}/share
@@ -15,7 +15,7 @@ VPATH = ../immscore:../analyzer:../model
 ARFLAGS = rs

 SHELL = bash
-PLUGINS = libxmmsimms.so
+PLUGINS = libxmmsimms.so libaudaciousimms.so
 OPTIONAL = immsremote analyzer

 GLIB2CPPFLAGS=`pkg-config glib-2.0 --cflags`
Index: imms-3.1.0-rc4/vars.mk.in
===================================================================
--- imms-3.1.0-rc4.orig/vars.mk.in      2008-03-02 18:54:06.000000000 -0700
+++ imms-3.1.0-rc4/vars.mk.in   2008-09-19 16:17:24.000000000 -0600
@@ -4,6 +4,7 @@ VERSION = @PACKAGE_VERSION@
 INSTALL = @INSTALL@
 prefix = @prefix@
 PREFIX = $(prefix)
+OBJCOPY = @OBJCOPY@
 OBJCOPYTARGET = @OBJCOPYTARGET@
 OBJCOPYARCH = @OBJCOPYARCH@
 exec_prefix = @exec_prefix@

Finally, make install doesn't finish the job.

cp build/libaudaciousimms.so /usr/local/lib/General/imms.impl

Well I think that's all the information you need, though it may not go smoothly. Hopefully we can get this all worked into IMMS proper and the 3.1.0 release will just work. If you use linux give Audacious+IMMS a try—it's easy and painless. If you think Audacious is for sissies, learn about the queue and the jump feature and try out IMMS for a week or two before you pass final judgement.

Oh, two final notes: Installing Torch can be a real pain and Audacious keyboard shortcuts don't work well with the gtk2 +quartz variant in MacPorts, so you want to stick with X11 gtk2. Oh, and though Audacious has a Last.fm plugin I haven't yet been able to figure out how to get it to stay enabled.

no comments |

Pipe Dream

Posted by Hans Fugal Wed, 25 Jun 2008 03:05:33 GMT

So I've been reading up on what makes organ pipes tick (ok, so they don't tick). It's very fascinating and yet very simple. It has surprised even me that it has made me think about making my own.

Now, I'm not crazy enough to build a large organ, at least not without gobs of time and money and the proper tools. I'm still nurturing the dream of building just a MIDI pedalboard, remember.

Still, there is a project that I can see myself taking on someday. I could build a positive organ. ("Positive" rhymes with "beef.") It's a little one-manual organ that has just a couple of stops. It's portable like a dresser with wheels is.

But not just any positive organ. A crazy simple positive organ. I'm thinking PVC pipe, because working with metal and wood intimidates me (and I don't have the tools). That may change before I actually build it. Who needs a case? If I'm going to build a pipe organ it's going to be naked so that people can see how an organ works. So build it onto/into a simple push cart or something. As for wind, what good is a portable organ if you have a loud motor that needs electricity? If I had cash for a nice quiet blower that would be one thing, but since I don't maybe I'll go with a simple bellows like they did in the olde days. Keyboard? Tracker's the only way to go on something like this, which means I'll have to break my anti-woodworking pact. But on a positive organ where the pipes are right there, the action should be simple.

This is very early stages of the dream, but I'm imagining 8', 4', 2', and 2 2/3'. 8' and 4' for sure. Probably 49 notes (4 octaves) on the manual. So that's 100–200 pipes. I hope my attention span is that large. Of course I can always start with one stop and go from there.

You may wonder how I'm going to fit an 8' stop in an organ I pretend will be portable. You can take a 4' pipe and cover the end and it will resonate like an 8' pipe (and though it's not made of wood will hopefully sound not entirely unlike a Gedackt).

If none of that made any sense, just click on this link and say "that'd be cool!"

no comments |

LilyPond on Leopard

Posted by Hans Fugal Wed, 27 Feb 2008 18:44:11 GMT

For my musical notation needs, I use LilyPond.

LilyPond is to music as LaTeX is to writing. I prefer to edit LilyPond files in Vim and compile them with lilypond at the command line. However, on OS X LilyPond.app is a front end to the compiler. An IDE of sorts. Not a spectacular one, in my opinion, but it does have one thing going for it: when you click on a note in the PDF preview, it takes you that note in your LilyPond source file in the IDE.

On Leopard, LilyPond is severely broken. The IDE will "start", but there is no menu. Further, if you are on Intel, when you try to run it at the command line, it just keels over and does nothing. It so happens that the workaround to this problem and using LilyPond without the IDE are almost identical solutions, so I'll describe them as one and the same.

First, and this is the only difference between Leopard brokenness and just wanting to run on the command-line, you want the powerpc version of LilyPond.app, not the Intel version. So go over to the download page and get the ppc version (the one that says it's for G3, G4, G5 Macs).

lilypond and its friends are in Lilypond.app/Contents/Resources/bin. You could add this to your PATH, but some of the binaries in there are things that I have installed elsewhere (e.g. with MacPorts), and I don't want them overriding my PATH. Likewise, I want lilypond to be able to find the binaries it expects, and since they're taking up disk space anyway let's help it along. So I wrote a script. A LilyPond launcher if you will. I call it ly and put it in my path, and then I call e.g. ly lilypond foo.ly. Here's the code:

#! /bin/sh
APP=/Applications/LilyPond.app
PATH=$APP/Contents/Resources/bin:$PATH
exec "$@"

Customize APP to point wherever you want to keep LilyPond.app. This will load up the environment that will give lilypond the best chance of success. You can run any of the binaries in that directory with ly, but the most common case is to run lilypond. So I recommend putting this in your .bashrc:

alias lilypond='ly lilypond'

The first time you run the ppc version of LilyPond, or anything else, on an Intel machine, it will seem to take forever while Rosetta fires up. Be patient. Subsequent invocations are quick enough.

3 comments |

Ogg Vorbis on OS X

Posted by Hans Fugal Mon, 25 Feb 2008 23:13:09 GMT

Once upon a time I was on a quest to get Ogg Vorbis working on a Mac. I tried the QuickTime Components project and it worked for awhile. Then it broke with QuickTime 7. Truth be known, it never worked all that great before, though it did decode the music. Then I found VLC and never looked back.

Today I learned that somewhere in the interim Xiph.org filled the gap. Now you can download XiphQT, stick XiphQT.component in /Library/Components, and you're off and running. This is precisely how the issue should have been addressed in the first place, and I'm glad it finally was, whenever it was. I'm also happy to have been ignorant of the fact for so long, since I despise iTunes for other reasons, and this tells me I've lived without regular iTunes abuse for a long hapy time.

1 comment |

Computer Music Seminar

Posted by Hans Fugal Wed, 01 Aug 2007 17:04:33 GMT

Today I presented a 1-hour seminar on Computer Music to a summer camp group here at New Mexico State University. We talked about what we can do with computers, demonstrated Ardour, Audacity, and GarageBand, and had a good listen to a few quality pieces. We even mentioned U2.

My presentation is available as a PDF, and it has links to all the interesting sites we mentioned. For those that weren't there, I'd like to point out especially Real World Remixed where you can download sample packs for some great music, including Peter Gabriel and Afro Celt Sound System songs, and remix them yourself with something like Ardour. Hours of fun!

no comments |

Unrefined "news site"

Posted by Hans Fugal Wed, 13 Dec 2006 14:31:33 GMT

For some time now Slashdot has ben getting more and more immature. Or I've been getting less tolerant of immaturity. I'm not sure which.

A story run yesterday was the last straw. It's time to move on. I'm removing Slashdot from my RSS feed.

The story was entitled Unrefined "Musician" Gains a Global Audience. Here is the blurb:

"An unskilled musician performed a catchy pop instrumental for more than one million YouTube users even though he can't play a lick of drums or piano. The 22-year-old Norwegian's tool was stop-motion video,

Hey Slashdot, guess what? If you compose music that people enjoy (i.e. catchy), you don't qualify as unskilled musician. This guy is obviously skilled at many things. He can obviously compose a catchy tune, knows a lot more about drums than I do, is very skilled with a video editing program, has a good comedic sense, and is good with a tracker. I know a number of composition majors at BYU who can play about as much piano, drums, or anything else as this guy. He and they compose music nonetheless and they are skilled musicians.

Skilled performer? No, at least not with those two instruments. But a skilled musician and video creator. Go watch Lesse Gjertsen's Amateur and Hyperactive. They're enjoyable.

Goodbye Slashdot, this reader has decided to leave your unrefined "news site" for the script kiddies.

Posted in | 2 comments |

ICMC 2006

Posted by Hans Fugal Sat, 16 Sep 2006 23:16:10 GMT

My GAANN fellowship will be sending me to New Orleans in November for the International Computer Music Conference (ICMC). I'm pretty psyched about this. I've never been to an academic conference, and I've certainly never been to a conference about Computer Music. It's going to be a blast, and it's going to be very informative. Hopefully I'll be able to network with some people in the field working on research similar to my own (which will begin in earnest in January, since my coursework is (almost) done after this semester). There will be Computer Music conferences, and I'll be sure to catch some good old New Orleans Jazz too.

I haven't asked yet, but I'm hoping GAANN will send me to the Linux Audio Conference in Berlin next year, too.

no comments |

On Sequencers

Posted by Hans Fugal Wed, 09 Aug 2006 14:11:00 GMT

I get the impression that most users of MIDI sequencers step record. At least, the writers of the sequencers pay little attention to live recording. For evidence, I cite the abundance of tracker sequencers available for Linux, and the three major sequencers for Linux (IMHO) which all fall short in the relatively simple task of accomodating people like me who prefer to record things live: Rosegarden, Muse, and Seq24.

Live recording is not complicated. You need a few basic features, and you need to make them accessible from the keyboard without touching the mouse. Here's an excellent UI model (that makes me drool):

Frontier Design Group's Tranzport

And here's a list of those basic features:

  • FF, REW, Stop, Play, Record
  • Replace and overdub modes.
  • Punch
  • Loop
  • Metronome
  • Lead-in of 2, 1, or 0 measures. My old Roland JW-50 from 1992 did a great job with this. You had the option of no lead-in but you also had the option of key-triggered recording. That is, you press record, and the thing starts recording the moment you start playing. This is extremely useful.
  • Track muting and solo
  • 16 tracks
  • Variable speed (percent of tempo) for slow and fast recording.
  • Undo

That's it. Most sequencers have some or perhaps even most of these features, but leave out essential aspects such as no mousing, replace recording, no lead-in, and not crashing. Rosegarden goes a step further and makes the simple things that you take for granted difficult as well (but it does everything else under the sun and it's hard to justify not using it).

Seq24 is unique in its failure because it is oriented at realtime performance. Note that word, "performance". It could perhaps just as easily be good at realtime recording if it tried, and then in spite of its loop and pattern-based approach it would still be an excellent sequencer for us non-pattern junkies. (Sequence a Bach organ fugue in a tracker, I dare you.)

If I have the honor of speaking to someone who is writing or improving a sequencer, please consider the keyboardists and take my thoughts into consideration. Believe it or not, the lack of these basics will drive a keyboardist crazy just as fast as mousing will drive a CLI junkie crazy. Which is quite ironic as most step-recording Linux sequencer developers are probably CLI junkies.

Posted in | 1 comment |

Knobtweakers Best of 2005 Compilation

Posted by Hans Fugal Tue, 11 Apr 2006 19:49:00 GMT

dilvie got me to add knobtweakers.net to my RSS feeds a while ago. Admittedly I usually don't listen to it (I need some good podcast software but that's another post). But the other day I did listen to the Enicma song Lost in an Unfriendly World, and I loved it. So I decided to see what else I might have missed and started digging around the site.

I downloaded the Knobtweakers Best of 2005 Compilation and listened to it today. There's some great stuff in there. Here's what I particularly liked.

Also deserving of honorable mention:

Almost all of the songs are right up my alley, but those are the ones that really stuck out at me after the first listen.

Oh, and while I'm on the subject, you ought to check out Computerville by Lunar Shuttle Disaster which is an excellent and fun piece made in Linux. Enjoy!

Posted in | 2 comments |