Things I’m thinking about and doing

I recently went to the M.C. Escher Museum, so I’ve now seen the originals of his crazy drawings. They are really mind-bending. I felt kind of dizzy as I left. The museum is cool, if a bit pricey. If you go, skip the top floor.
Yesterday, my new bike arrived. It is gigantic. It weights 50% of my body weight. I always get things that are too big. My clothes. My bass speaker cabinet. I’m such a size queen. This is probably why I play tuba. Anyway, the bike is awesome. I think I’m going to swap the seat for a leather one. (I so suck at being vegan-ish.) This weekend, we’re going to bike to the sea. The next weekend, we’re going to bike to Delft. Bike = awesome. I love bikes.
I started trying to integrate my joystick into my cheesy live sampling application that I built. It’s educational. Also, I’m wondering if I should make the action more like the action for SCButton. That passes itself as the sole argument. If you want the value, you ask the button for the value. It’s kind of more logical. All of the things that I pass to the button action are things that the element (read: particular sensor) already knows. So, I’m pondering another re-write of my class. I think I probably will.
The school’s fire alarm is going off. I wonder if this has any implications.
Tags: ,

Concert Report

On Sunday afternoon, I played a couple of pieces at the <TAG> Gallerie in The Hague. I got this gig through a myspace connection. Myspace actually works for composers and musicians! You should sign up and post mp3s. It’s a way to get people to listen to your music and maybe go to your real website. Plus you can come up with a metric for judging your self-worth by the number of people who “friend” you. Since hardly anybody will ever de-friend you, your list of friends will keep growing. I have 300 “friends” including dead composers, fictional characters, porn stars, people I know in real life, and Luc, the guy who arranged the gig.
Anyway, the concert started with a trio of Han Buhrs, Guy Harries and Luc Houtkamp doing a sort of planned improv. Then Kader Abdolah talked for a while in Dutch about the history of music and text in Persia. Music was disallowed for a while, but the Qur’an is very rhythmic and so it was declaimed in a very musical manner, but not called music. Also, Dutch has many cognates with English, French and German, but I really need to take a class. Then I played Meditations pour les Femmes, then there was a break, then I played Faux-bourdon Bleu, then the previous trio came back but with the addition of Joseph Bowie on trombone. They did sort of improv cabaret stuff, which was fun.
During the whole thing there was a pair of stereo mics in the back for recording, next to a tripod-mounted video camera. Two people had handheld cameras and were also filming from either side. A guy was also taking pictures. Afterwards, two of the video cameras were used to interview everybody who had been on stage. Cola noted that it was the single most documented concert that she had ever been to.
The guy who interviewed me was surprised to hear that I was new in town, because he was hanging out in the studio of a radio station last week and they were playing a piece of mine Virtual Memory. That piece is truly irritating and terrible. He said that they stopped it before it was finished because it was too awful. The good news is I’ve been played on the radio in The Netherlands. The bad news is that it’s an irritating piece that will not bring me fame, fortune and women.
(You may wonder why I posted it to my web site if it is so fingernails-on-chalkboard. I did because to me it sounds very similar to some of the results of using Gendyn oscillators, which are Xenakis-designed algorithms for using stochastic noise to produce wave forms. They sound like data and Virtual Memory IS data, specifically the contents of my virtual memory buffer on OS 9.)
Anyway, I talked to the guy who (I think) was the DJ who played this harsh mp3 and I might be on the radio in person next month. The time for the show is very nocturnal for Europe, but it’s also webcast and is in the middle of the day for America.
My friend Polly was on the radio in California on KFJC and the next week, she was the most requested artist on the radio station. Which is awesome for her and is a testament to her music, but also shows the power of an interview. But, alas, I have no record out to promote, although I have one out of print and one never-in-print and enough cohesive material for one or two more. Maybe the album paradigm is dead and the future will all be mp3s on the web? On a theoretical level, I’m in favor of low-fi. I use the headphone outs on my computer instead of an expensive d->a converter. But there is noticeable quality loss for the mp3s, even at the relatively high compression rate that I use. (Can I be both lo-fi and rue a loss in richness?) (Obviously the album paradigm is dead, as I haven’t been approached by a record company.)Tags: ,

HID Update

Download a new version of my HID classes.
So I think some of my original features were overzealous, so some of them have been removed. For instance, no more specifying a ControlSpec for an HIDElementExt. If you want to use a ControlSpec, you should attach the HIDElementExt (or HIDElement Group) to a CV by means of the action. Remember that CVs are really useful objects. See their help file for more information. For example of how to attach one:

element.action_({arg vendorID, productID, locID, cookie, value;

 var scaled, mycv;
     
 scaled = element.scale(value);
         
 mycv = cvDictionary.at(element.usage.asSymbol);
 mycv.input_(scaled);
});

Note the name and order of arguments, as this is a change. In this example, cvDictionary is an IdentityDictionary where CVs are stored according to the element.usage as a key. scale is a message you can pass to an element in which a value is scaled according to the min and max to be a number between 0 and 1. You can still set the min and max of an element based on what you’ve discovered to be the range of your HID, regardless of what lies the device may whisper in your ear about it’s ranges.
The HIDDeviceExt.configure message was not really needed, so it’s gone.
Here is some code to automatically generate a GUI for every HID that you have attached. Note that you will need the Conductor class for it, which is part of the Wesleyan nightly build. This GUI will give you one line for every reported piece of the device. You can then try moving everything around to see what their actual ranges are (if they are smaller than reported) and the correlation between reported names and the elements.

(

 var elems, names, cv, conductor;

 HIDDeviceServiceExt.buildDeviceList;
 
 HIDDeviceServiceExt.devices.do({ arg dev;
 
  elems = [];
  names = [];

  dev.queueDevice;

  dev.elements.do ({ arg elm;
  
   cv = CV.new.sp(0, elm.min, elm.max, 0, 'linear');
   elems = elems.add(cv);
   names = names.add(elm.usage.asSymbol);
   elm.action_({ arg vendorID, productID, locID, cookie, value;
     
    var scaled, mycv;
     
    scaled = elm.scale(value);
         
    mycv = conductor.at(elm.usage.asSymbol);
    mycv.input_(scaled);
   });

  });
 
  conductor = Conductor.make({ arg cond; 
  
   elems.do({ arg item, index;
   
    cond.put(names[index], item);
   });
   
   cond.argList = cond.argList ++ elems;
   cond.argNames = cond.argNames ++ names;
   cond.valueItems = cond.valueItems ++ names;
   cond.guiItems = cond.valueItems;
  });
  
  conductor.show;
  
 });
 
 HIDDeviceServiceExt.runEventLoop;

)

Then stop it with:

HIDDeviceServiceExt.stopEventLoop;

But what if the returned values are outside of the range? And what are the cookies? You should then generate a little report to correlate everything.

(
 HIDDeviceServiceExt.devices.do({arg dev;
  [dev.manufacturer, dev.product, dev.vendorID, dev.productID, dev.locID].postln;
  dev.elements.do({arg ele;
   [ele.type, ele.usage, ele.cookie, ele.min, ele.max, ele.minFound, ele.maxFound].postln;
  });
 });
)

You can use the minFound and maxFound data to calibrate the device.
This is my current code to configure my (crappy) joystick:

HIDDeviceServiceExt.buildDeviceList;
HIDDeviceServiceExt.queueDeviceByName('USB Joystick STD');

(

 var thisHID, simpleButtons, buttons, stick;
 
 thisHID = HIDDeviceServiceExt.deviceDict.at('USB Joystick STD');
 simpleButtons = HIDElementGroup.new;
 buttons = HIDElementGroup.new;
 stick = HIDElementGroup.new;
  
 thisHID.deviceSpec = IdentityDictionary[
   // buttons
   trig->7, left->9, right->10, down->8, hat->11,
   // stick
   x->12, y->13,
   wheel->14,
   throttle->15
  ]; 
  
  
 simpleButtons.add(thisHID.get(trig));
 simpleButtons.add(thisHID.get(left));
 simpleButtons.add(thisHID.get(right));
 simpleButtons.add(thisHID.get(down));
  
 buttons.add(simpleButtons);
 buttons.add(thisHID.get(hat));
  
 stick.add(thisHID.get(x));
 stick.add(thisHID.get(y));
  
 // make sure each element is only lsted once in the nodes list, or else it
 // will run it's action once for each time a value arrives for it
  
 thisHID.nodes = [ buttons, stick, thisHID.get(wheel), thisHID.get(throttle)];
  
 // When I was testing my joystick, I noticed that it lied a bit about ranges
  
 thisHID.get(hat).min = -1;  // it gives back -12 for center, but -1 is close enough
  
 // none of the analog inputs ever went below 60
  
  
 thisHID.get(wheel).min = 60;
 thisHID.get(throttle).min = 60;
 // can set all stick elements at once
 stick.min = 60;
)

Setting the min and the max for each element is used for the scale message. If you don’t want to bother scaling the values to be between 0 and 1 (or some other range) and you set the threshold to 0, then you can skip setting the min and the max.
Here is a silly example of using the x and y axis of my joystick to control the frequency and amplitude of a Pbind in a GUI. Note that it would work almost identically without the GUI.

(

 HIDDeviceServiceExt.runEventLoop;

 Conductor.make({arg cond, freq, amp;
 
  var joystick;
 
  freq.spec_(freq);
  amp.spec_(amp);
  
  joystick = HIDDeviceServiceExt.deviceDict.at('USB Joystick STD');
  
  joystick.get(y).action_({ arg vendorID, productID, locID, cookie, value;
  
   freq.input_(joystick.get(y).scale(value));
  });
  
  joystick.get(x).action_({ arg vendorID, productID, locID, cookie, value;
  
   amp.input_(joystick.get(x).scale(value));
  });
  
  cond.name_("silly demo");
  
  cond.pattern_( Pbind (
  
   freq, freq,
   amp, amp
  ));
  
 }).show;
  
)

Don’t forget to stop the loop when you’re done:

HIDDeviceServiceExt.stopEventLoop;

As you may have guessed from this EventLoop business, HIDs are polled. Their timing, therefore, may not be as fast as you’d like for gaming. They may be more suited to controlling Pbinds like in the silly example, rather than Synth objects. You will need to experiment on your own system to see what will work for you.
The HIDElementExt all have a threshold of change below which they will not call their actions. This defaults to 5%, which is a good value for my very crappy joystick. You can set your own threshold. It’s a floating point number representing a percent change, so you can put it between 0 and 1. Again, you may want to experiment with this. Most HIDs have a little bit of noise and flutter where they report tiny actions where none occurred. Also, do not buy a 5€ joystick from a sketchy shop. It’s range will suck and it will will flutter like crazy and it will be slow and you will end up buying a more expensive joystick anyway.

joystick.threshold_(0.01); // 1% 

Tags: , ,

“Bank” means “sofa” in Dutch

But it’s a good thing they’re different things, or nobody would let me sit anywhere. I have gone to every bank chain in the city, as far as I know. I have never encountered anybody who wanted my business less. What is causing this?
All of my American classmates have managed to open accounts, so it’s not anti-Americanism. Is it sexism? Is it homophobia? Do I not closely enough look like a student? Am I too butch for them? Not manly enough?
I ask for an account and they start looking for reasons to say no. Note that I don’t say that they’re listing requirements. They quite clearly want to refuse me. Given that I’ve gone to the same banks as my classmates, I can only assume that I’m experiencing discrimination. I was hoping that being the recipient of antigay slurs at the train station was an isolated event, but maybe not. Or maybe it’s something else.
I really miss France. Their bureaucracy is way easier and more logical than here. And when it wasn’t, one could always resort to yelling. I don’t think that will help here, but I’m about a millimeter away from it.
Tags: ,

Biography, programs and music

A while ago, I had a conversation with a friend who contended that people go to concerts, read the biographies (and program notes) of a composer and judge the pieces based on this rather than on the sound. He furthermore stated that many biographies of students were inflated. They had played concerts in their home towns, their college towns and now here, perhaps in three different countries. But they’re not international stars, it’s just where they studied. Furthermore, who their teachers were might be important, but it’s not germane to listening to the piece. If these composers are so fantastic, why are they in school at all? (Maybe they just want to live in another country until Habeas Corpus is reinstated.)
I’ve been thinking about this in regards to my bio. I think having a bio that lists teachers, education, awards and whatnot is useful for a press kit. As in: anything that helps me get gigs is good. But what about a bio for programs? Apparently, according to my (non-Dutch) friend, the Dutch don’t react well to self aggrandizement. So I’ve thought about having a different short bio for use in printed programs at musical performances.
Nicole says it’s too weird. She may be right, as it might not fully encourage people to judge my music on it’s merits rather than a perception of me that they gleam from my printed statement. But it’s not self-aggrandizing and does get to the heart of certain issues. So I’m asking you, dear readers, too weird or just right?

Celeste Hutchins is a Californian abroad, testing Philip K Dick’s theory that once you become a Berkeley radical, you can never leave. She explores issues of regional identity, plays music, goes to school and has telepathic conversations with an alien satellite orbiting the earth.

Tag:

HID, Joysticks and SuperCollider

So, game controllers and joysticks and the like are called Human Interface Devices (HID). There is some HID stuff built into SuperCollider, but it seemed sort of half implemented. They let you specify things, but not do much with it. So I wrote an extension yesterday, which maybe I should submit as something official or a replacement, although I didn’t bother checking first if anybody else had already done anything. No internet access at home sucks.

To use it, download HID.sc and put it in ~/Library/Application Support/SuperCollider/Extensions. Plug in your joystick or controller. Start SuperCollider.
First, you want to know some specifications for your device, so execute:


HIDDeviceServiceExt.buildDeviceList;

  
(
HIDDeviceServiceExt.devices.do({arg dev;
  [dev.manufacturer, dev.product, dev.vendorID, dev.productID, dev.locID].postln;
  dev.elements.do({arg ele;
   [ele.type, ele.usage, ele.cookie, ele.min, ele.max].postln;
  });
});
)

I got back:

  [ , USB Joystick STD, 1539, 26742, 454033408 ]
  [ Collection, Joystick, 1, 0, 0 ]
  [ Collection, Pointer, 2, 0, 0 ]
  [ Button Input, Button #5, 3, 0, 1 ]
  [ Button Input, Button #6, 4, 0, 1 ]
  [ Button Input, Button #7, 5, 0, 1 ]
  [ Button Input, Button #8, 6, 0, 1 ]
  [ Button Input, Button #1, 7, 0, 1 ]
  [ Button Input, Button #2, 8, 0, 1 ]
  [ Button Input, Button #3, 9, 0, 1 ]
  [ Button Input, Button #4, 10, 0, 1 ]
  [ Miscellaneous Input, Hatswitch, 11, 0, 3 ]
  [ Miscellaneous Input, X-Axis, 12, 0, 127 ]
  [ Miscellaneous Input, Y-Axis, 13, 0, 127 ]
  [ Miscellaneous Input, Z-Rotation, 14, 0, 127 ]
  [ Miscellaneous Input, Slider, 15, 0, 127 ]
  [ a HIDDevice ]

Ok, so I know the name of the device and something about all the buttons and ranges it claims to have. (Some of them are lies!) So, I want to assign it to a variable. I use the name.

j = HIDDeviceServiceExt.deviceDict.at('USB Joystick STD');

Ok, I can set the action for the whole joystick to tell me what it’s doing, or I can use the cookie to set the action for each individual element. I want to print the results. In either case, the action would look like:

x.action = { arg value, cookie, vendorID, productID, locID, val;
 [ value, cookie, vendorID, productID, locID, val].postln;
};

You need to queue the device and start the polling loop before the action will execute.

HIDDeviceServiceExt.queueDeviceByName('USB Joystick STD');
HIDDeviceServiceExt.runEventLoop;

It will start printing a bunch of stuff as you move the controls. When you want it to stop, you can stop the loop.

 HIDDeviceServiceExt.stopEventLoop; 

Ok, so what is all that data. The first is the output of the device scaled to be between 0-1 according to the min and max range it reported by the specification. The next is very important. It’s the cookie. The cookie is the ID number for each element. You can use that to figure out which button and widget is which. Once you know this information, you can come up with an IdentityDictionary to refer to every element by a name that you want. Mine looks like:

  j.deviceSpec = IdentityDictionary[
   // buttons
   a->7, left->9, right->10, down->8, hat->11,
   // stick
   x->12, y->13,
   wheel->14,
   throttle->15
  ]; 

The last argument in our action function was the raw data actually produced by the device. You can use all your printed data to figure out actual ranges of highs and lows, or you can set the action to an empty function and then restart the loop. Push each control as far in every direction that it will go. Then stop the loop. Each element will recall the minimum and maximum numbers actually recorded.

(
j.elements.do({arg ele;
   [ele.type, ele.usage, ele.cookie, ele.min, ele.max, ele.minFound, ele.maxFound].postln;
  });
)

This gives us back a table like the one we saw earlier but with two more numbers, the actual min and the actual max. This should improve scaling quite a bit, if you set the elements min and max to those values.   ele.min = ele.minFound;   Speaking of scaling, there are times when you want non-linear or within a different range, so you can set a ControlSpec for every element. Using my identity dictionary:

j.get(throttle).spec = ControlSpec(-1, 1, step: 0, default: 0);

Every element can have an action, as can the device as a whole and the HIDService as a whole. You can also create HIDElementGroup ‘s which contain one or more elements and have an action. For example, you could have an action specific for buttons. (Note that if you have an action for an individual button, one for a button group and one for the device, three actions will be evaluated when push the button.) Currently, an element can only belong to one group, although that might change if somebody gives me a good reason.
This is a lot of stuff to configure, so luckily HIDDeviceExt has a config method that looks a lot like make in the conductor class. HIDDeviceExt.config takes a function as an argument. The function you write has as many arguments as you want. The first refers to the HIDDeviceExt that you are configuring. The subsequent ones refer to HIDElementGroup ‘s. The HIDDeviceExt will create the groups for you and you can manipulate them in your function. You can also set min and max ranges for an entire group and apply a ControlSpec to an entire group. My config is below.

 j.config ({arg thisHID, simpleButtons, buttons, stick;
  
  thisHID.deviceSpec = IdentityDictionary[
   // buttons
   a->7, left->9, right->10, down->8, hat->11,
   // stick
   x->12, y->13,
   wheel->14,
   throttle->15
  ]; 
  
  
  simpleButtons.add(thisHID.get(a));
  simpleButtons.add(thisHID.get(left));
  simpleButtons.add(thisHID.get(right));
  simpleButtons.add(thisHID.get(down));
  
  buttons.add(simpleButtons);
  buttons.add(thisHID.get(hat));
  
  stick.add(thisHID.get(x));
  stick.add(thisHID.get(y));
  
  // make sure each element is only lsted once in the nodes list, or else it
  // will run it's action once for each time a value arrives for it
  
  thisHID.nodes = [ buttons, stick, thisHID.get(wheel), thisHID.get(throttle)];
  
  // When I was testing my joystick, I noticed that it lied a bit about ranges
  
  thisHID.get(hat).min = -1;  // it gives back -12 for center, but -1 is close enough
  
  // none of the analog inputs ever went below 60
  
  
  thisHID.get(wheel).min = 60;
  thisHID.get(throttle).min = 60;
  // can set all stick elements at once
  stick.min = 60;
      
  // ok, now set some ControlSpecs
  
  thisHID.get(hat).spec = ControlSpec(0, 4, setp:1, default: 0);
  // set all binary buttons at once
  simpleButtons.spec = ControlSpec(0, 1, step: 1, default: 1);
  
  // all stick elements at once
  stick.spec = ControlSpec(-1, 1, step: 0, default: 0);
  thisHID.get(wheel).spec = ControlSpec(-1, 1, step: 0, default: 0);
  thisHID.get(throttle).spec = ControlSpec(-1, 1, step: 0, default: 0);
  
  thisHID.action = {arg value, cookie, vendorID, productID, locID, val;
  
   [value, cookie, vendorID, productID, locID, val].postln;
  };
   
 });

I wrote all of this yesterday, so this is very demo/pre-release. If something doesn’t work, let me know and I’ll fix it. If people have interest, I’ll post better versions in the future.
Tags: , ,

Concert Announcement

8 Oktober: Over tekst en muziek – Kader Abdolah

Kader Abdolah – lezing over de relatie tussen tekst en muziek
Han Buhrs – zang, live elektronica
Joseph Bowie – trombone, zang, live elektronica
Luc Houtkamp – computer, saxofoon
Guy Harries – computer, zang
Celeste Hutchins – compositie, computer
Kader Abdolah, Nederlands schrijver van Iraanse afkomst, zal een lezing houden over de synthese tussen poëzie en muziek in de Perzische cultuur. Abdolah heeft met het POW Ensemble een voorstelling gemaakt voor het Crossing Border festival 2005, waarin de gedichten van de Perzische dichter Jalaluddin Rumi een centrale rol innemen. Bij het werkproces aan dat project is het ons opgevallen hoe nauw muziek en poëzie in de Perzische cultuur samen vallen. Kader Abdolah heeft over dit gegeven veel te vertellen.
De relatie tussen tekst en muziek is een onderwerp dat het POW Ensemble ten zeerste bezighoudt. Het ensemble legt de verbinding tussen beiden op een eigentijdse manier door gebruik te maken van computers. Op dit concert zullen we laten horen wat de mogelijkheden van deze werkwijze zijn.
Daarnaast zal de Amerikaanse componiste Celeste Hutchins haar composities Meditations pour les Femmes en Faux-bourdon Bleu te gehore brengen.

Plaats: Galerie <TAG>, Stille Veerkade 19, tel. 070-3468500 Aanvang: 16:00 uur (deuren open om 15:30)
Toegang 5 euro (studenten 2,50 euro) Passe partout voor 4 concerten: 15 euro

Which is to say that I’ll be playing 2 pieces in a larger concert on October 8 at 4:00 PM at Galerie <TAG>, Stille Veerkade 19, The Hague. Tel. 070-3468500. Price is 5€ or 2.50€ for students. If you want to go to the whole series (you missed the first one (ack, I forgot the first one)), it’s 15€.
Tags: ,

Heh heh. She said “Joystick”

Is it me, or is everything about game devices loaded with innuendo? “Joy stick?” I mean, really. I went out yesterday and attempted to purchase one called the “thrust master.” Sublimation much?
No, I have not discovered the joys of gaming. (Well, I briefly became interested in a Soduku widget, but it got old fast. Closely related to minesweeper but without the smiley face or the implied violence. bah.) If I gamed, I would not do anything else. It’s difficult for me to compartmentalize.
Anyway, I found a bargain joystick with 2 degrees of A->D conversion for the stick and another degree for the throttle. I have plans to use it with my tuba (or, rather, my formerly bubblewrapped sousaphone). If the stick proves too awkward / stupid, then different variable resistors, such as ribbons can be put in place of where the stick went.
Right now, though, I am giggling like a middle schooler at game device terminology. If I remove the plastic of the handle and replace it with a cyberskin packer, would this be over-the-top for performance? What if it was crotch-mounted?
(For those of you wondering what a “cyberskin packer” is: It’s a limp, squishy prosthetic penis that one might use for stuffing their trousers. These are used by Drag Kings, FTMs, cisgender males with injuries, and people who know how to get a party started. And very serious gamers, of course.)
Tag:

Weekend Trips not to Take

Leave The Hague at 12:30 PM, Drive to Paris. Eat. Sleep. Carry all belongings down 3 flights of stairs. Drive back to The Hague. Leave girlfriend and all belongings at a gas station. Carry all belongings the few blocks from the gas station, through the pedestrian area, to apartment. Move all belongings up steepest flights of stairs ever. Wonder why knee hurts.

#2

Cut Friday classes. Go to train station. Take train to airport. Get on plane. Fly to San Francisco. Borrow Car. Drive to Santa Cruz. Eat. Get drunk. Go dancing. (awake for 26 hours!) Collapse. Awake. Eat. Get lost trying to find beach. Drive to Berkeley. Eat. Sleep. Drive to Santa Cruz. Watch brother get married. Eat. Drive to San Jose. Eat. Drive to Berkeley. Sleep. Try to buy tuba shipping case. Give up. Buy bubble wrap. Wrap sousaphone in bubble wrap. Get ride to airport. Fly to Amsterdam. Get on wrong train. Wander around train station of small town in Holland while carrying bubble wrapped sousaphone. Take train to The Hague. Carry bubble wrapped tuba to apartment. Fall asleep. Miss classes. Forget lab time.
This weekend, I’m thinking of going to Amsterdam to get my hair cut.
Um, anyway, my brother got married and I came back for it and went to the Bachelorette party (my first and last, I think). And I now have the worst tuba in Holland, I think. I didn’t worry about breaking it because who could tell. It sounds like a wounded cow. I want to use it to work out how to do some stuff which I will later do with a real tuba.
My stomach still hurts from the antibiotics that I took in July. This is ridiculous. I go offline to find a medical person to whine to.
Tags: ,