Some Source Code

Yesterday, I posted some links to a supercollider class, BufferTool and it’s helpfile. I thought maybe I should also post an example of using the class.
I wrote one piece, “Rush to Excuse,” in 2004 that uses most of the features of the class. Program notes are posted at my podcast. And, The code is below. It requires two audio files, geneva-rush.wav and limbaugh-dog.aiff You will need to modify the source code to point at your local copy of those files.
The piece chops up the dog file into evenly sized pieces and finds the average pitch for each of them. It also finds phrases in Rush Limbaugh’s speech and intersperses his phrases with the shorter grains. This piece is several years old, but I think it’s a good example to post because the code is all cleaned up to be in my MA thesis. Also, listening to this for the first time in a few years makes me feel really happy. Americans finally seem to agree that torture is bad! Yay! (Oh alas, that it was ever a conversation.)

(

 // first run this section

 var sdef, buf;
 
 
 // a callback function for loading pitches
  
 c = {

  var callback, array, count;

    array = g.grains;
    count = g.grains.size - 1;
     
    callback = { 
   
     var next, failed;
      
     failed = true;
      
     {failed == true}. while ({
    
      (count > 0 ). if ({
    
       count = count -1;
       next = array.at(count);
    
       (next.notNil).if ({
        next.findPitch(action: callback);
        failed = false;
       }, {
        // this is bad. 
        "failed".postln;   
        failed = true;
       });
      }, { 
       // we've run out of grains, so we must have succeeded
       failed = false;
       "pitch finding finished".postln;
      });
     });
    };
   
   };

 
 // buffers can take a callback function for when they finish loading
 // so when the buffer loads, we create the BufferTools and then
 // analyze them
  
   buf = Buffer.read(s, "sounds/pundits/limbaugh-dog.aiff", action: {
  
    g = BufferTool.grain(s, buf);
    h = BufferTool.grain(s, buf);
    "buffers read!".postln;
   
  g.calc_grains_num(600, g.dur);
    g.grains.last.findPitch(action: c.value);
    h.prepareWords(0.35, 8000, true, 4000);
 
   });
 
   i = BufferTool.open(s, "sounds/pundits/geneva-rush.wav");

  
   sdef = SynthDef(marimba, {arg out=0, freq, dur, amp = 1, pan = 0;
  
   var ring, noiseEnv, noise, panner, totalEnv;
   noise = WhiteNoise.ar(1);
   noiseEnv = EnvGen.kr(Env.triangle(0.001, 1));
     ring = Ringz.ar(noise * noiseEnv, freq, dur*5, amp);
     totalEnv = EnvGen.kr(Env.linen(0.01, dur*5, 2, 1), doneAction:2);
     panner = Pan2.ar(ring * totalEnv * amp, pan, 1);
     Out.ar(out, panner);
    }).writeDefFile;
   sdef.load(s);
   sdef.send(s);

   SynthDescLib.global.read;  // pbinds and buffers act strangely if this line is omitted

)

// wait for: pitch finding finished

(

 // this section runs the piece

 var end_grains, doOwnCopy;
 
 end_grains = g.grains.copyRange(g.grains.size - 20, g.grains.size);
 

 // for some reason, Array.copyRange blows up
 // this is better anyway because it creates copies of
 // the array elements

 // also:  why not stress test the garbage collector?
 
 doOwnCopy = { arg arr, start = 0, end = 10, inc = 1;
 
  var new_arr, index;
  
  new_arr = [];
  index = start.ceil;
  end = end.floor;
  
  {(index < end) && (index < arr.size)}. while ({
  
   new_arr = new_arr.add(arr.at(index).copy);
   index = index + inc;
  });
  
  new_arr;
 };

 
 
 Pseq( [


  // The introduction just plays the pitches of the last 20 grains
  
  Pbind(
 
   instrument, marimba,
   amp,   0.4,
   pan,   0,
   
   grain,   Pseq(end_grains, 1),
   
   [freq, dur],
      Pfunc({ arg event;
     
       var grain;
      
       grain = event.at(grain);
       [ grain.pitch, grain.dur];
      })
  ),
  Pbind(
  
   grain, Prout({
   
      var length, loop, num_words, loop_size, max, grains, filler, size,
       grain;
      
      length = 600;
      loop = 5;
      num_words = h.grains.size;
      loop_size = num_words / loop;
      filler = 0.6;
      size = (g.grains.size * filler).floor;
      
      
      grains = g.grains.reverse.copy;

      // then play it straight through with buffer and pitches

      {grains.size > 0} . while ({
        
       //"pop".postln;
       grain = grains.pop;
       (grain.notNil).if({
        grain.yield;
       });
      });
      
      
      loop.do ({ arg index;
      
       "looping".postln;
      

       // mix up some pitched even sizes grains with phrases

       max = ((index +2) * loop_size).floor;
       (max > num_words). if ({ max = num_words});
       
       grains = 
         //g.grains.scramble.copyRange(0, size) ++
         doOwnCopy.value(g.grains.scramble, 0, size) ++
         //h.grains.copyRange((index * loop_size).ceil, max);
         doOwnCopy.value(h.grains, (index * loop_size).ceil, max);
         
       

       // start calculating for the next pass through the loop
       
       length = (length / 1.5).floor;
       g.calc_grains_num(length, g.dur);
       g.grains.last.findPitch(action: c.value);
       
       grains = grains.scramble;
       

       // ok, play them
       
       {grains.size > 0} . while ({
        
        //"pop".postln;
        grain = grains.pop;
        (grain.notNil).if({
         grain.yield;
        });
       });
      });
      
      i.yield;
      "end".postln;
     }),
   [bufnum, dur, grainDur, startFrame, freq, instrument], 
    Pfunc({arg event;
    
     // oddly, i find it easier to figure out the grain in one step
     // and extract data from it in another step
     
     // this gets all the data you might need
    
     var grain, dur, pitch;
     
     grain = event.at(grain);
     dur = grain.dur - 0.002;
     
     pitch = grain.pitch;
     
     (pitch == nil).if ({
      pitch = 0;
     });
     
     [
      grain.bufnum,
      dur,
      grain.dur,
      grain.startFrame,
      pitch,
      grain.synthDefName
     ];
     
    }),
      
      
   amp,   0.6,
   pan,   0,
   xPan,   0,
   yPan,   0,
   rate,   1,
   
   
   twoinsts, Pfunc({ arg event;
       
     // so how DO you play two different synths in a Pbind
     // step 1: figure out all the data you need for both
     // step 2: give that a synthDef that will get invoked no matter what
     // step 3: duplicate the event generated by the Pbind and tell it to play
       
       var evt, pitch;
       
       pitch = event.at(freq);
       
       (pitch.notNil). if ({

        // the pitches below 20 Hz do cool things to the 
        // speakers, but they're not really pitches,
        // so screw 'em
        
        (pitch > 20). if ({
         evt = event.copy;
         evt.put(instrument, marimba);
         evt.put(amp, 0.4);
         evt.play;
         true;
        }, {
         false;
        })
       }, {
        // don't let a nil pitch cause the Pbind to halt
        event.put(freq, rest);
        false;
       });
      })
        
  )      
      
       
 ], 1).play
)
 

This code is under a Creative Commons Share Music License

BufferTool

A while back, I wrote some code and put it in a class called BufferTool. It’s useful for granulation. Any number of BufferTools may point at a single Buffer. Each of them knows it’s own startFrame, endFrame and duration. Each one also can hold an array of other BufferTools which are divisions of itself. Each one may also know it’s own SynthDef for playback and it’s own amplitude. You can mix and match arrays of them.
You can give them rules for how to subdivide, like a set duration of each grain, a range of allowable durations or even an array of allowed duration lengths. Or, it can detect pauses in itself and subdivide according to them. It can calculate the fundamental pitch of itself.
I want to release this as a quark, but first I’d like it if some other people used it a bit. The class file is BufferTool.sc, and there’s a helpfile and a quark file.
Leave comments with feedback, if you’d like.

Manners

British people keep telling me I’m very polite. In fact, my girlfriend complained that I’m too polite. I keep thinking this would be a shocking revelation to people at home, who seem to have rather the opposite idea about me. I’ve come up with a few possible reasons for this change:
Dry humor. The British sense of humor involves a lot of sarcasm. Maybe they’re all saying this because it’s not true. Alas.
I’ve changed. Maybe with age I’ve gained a bit of tact and whatnot?
Cultural differences. Maybe Americans just have much higher standards than Brits. Also, I’m not exactly hanging out with the royal family. And, to be fair, it seems they would have even lower standards.
Gendered expectations. It’s possible that people expect a lot less from men than women. Or perhaps what they expect is just different and I did not conform to the standard female model and my laxish manners are good enough for blokes? I find this explanation both likely and annoying. Casual sexism is bad, people!
Anyway, none of this pondering matters to those of you who remember the good old days when I used to run around in my underwear while belching as loudly as possible. Ah, good times. I miss them.

The Swine Flu / The Economy

What’s your take on the media? Pick one.
The swine flu:

  1. is a distraction from the failures of capitalism – which are solvable with collective action.
  2. we’re all jonesing for the apocalypse.
  3. the inevitable consequences of farming and/or slaughtering animals – which also accounts for diseases like the bird flu and HIV.
  4. I caught the sniffles at the last tea-bagging rally I went to. Should I be worried?

Speaking of tea-bagging rallies, a commenter on my previous post suggested that it would be a waste of effort to try to connect with the people at these things because of massive disagreement on issues. I think that the masses on the left and the right actually have quite a bit of populist rage in common: why are my taxes going to bankers?! What differs is largely our answers to that question and out ideas how to fix it. There are those who will be swayed by a fascist argument. Many of those people, though, are not stupid, just misinformed. The fascist argument is the only one that they’ve heard.
Some of the people at the tea rallies have a hard time giving coherent answers to journalists’ questions. Similarly, many people at the G20 rallies also had trouble formulating a coherent answer. Part of the reason for this is because the frames and assumptions for the questions are trying to obscure rather than enlighten. They’re asking the wrong questions. Here’s the answer to the right question: We on the left and the right are all similarly angry that people with too much power and no accountability decided to use all of our resources and wealth as play money in a giant game and now we’re facing artificial shortages and the folks that caused all this get to keep all the money they stole.
When the economy gets fucked, we’re in a precarious situation not just economically, but also due to the danger of fascism. If we want to feel superior to people being recruited to fascism, we’re doomed. That’s not a reasonable strategy. People will be radicalized by the economy. There will be a surge of power on the very far right. Lefty smugness is enabling to fascists. If we want to limit this, we need to be talking to people about why our solutions are going to be better for them.
Anti-capitalists are actually correct, which ought to be a serious advantage. But our smugness is dressed up classism and we need to get over it or we’ve got no answers, just more status-quo.

Teabagging

The image that pops into your head on my post title up there says a lot about where you fall on the political spectrum in the US. For those of you thinking about unsanitary practices, there was recently some discontent about taxes in the US, as there often is. And long ago, there was the Boston Tea Party, where angry revolutionaries threw cases of tea off of a boat rather than have anybody pay taxes on them. Somebody more recently was inspired by this story and organized a protest where people would throw tea into a body of water. And since loose leaf tea is uncommon, or, at the very least, more expensive than Lipton, tea bags were littered into a water way. This seemed like an idea worth copying on other places and somebody gave it the name “teabagging.” Somebody wholesome gave it that name.
These unfortunately-named parties were not originally organized by the Republican party, but they seized on it. Now if you want to see somebody holding up a sign calling Obama a Nazi, a Muslim, s Socialist or the Anti-Christ, well, here’s the venue for you. It’s too easy for us urban elites to mock these parties. They share a name with a sex act. They attract spectacularly misinformed people, some of whom are clearly racist. But I think it’s an error to dismiss them out of hand.
How many of you, when writing you check for the last tax day, thought of some of it going to a $5 million AIG bonus? Or some kind of bank or financial institution. Admit it, you felt even less good about mailing in your check than usual. What’s the point, they’re just going to give it to a hedge fund, right? This annoyance you feel could be rage. Maybe it should be rage. Houses sit empty while homelessness grows and we give our tax money to bankers!
If you ask any of the folks at these tea-tossing rallies what they think the word “socialism” means, they will start talking to you about giving away money to banks. If you say, “what if we spent it on healthcare for everybody instead?” most of them would think that was a good idea. These folks actually want a mixed-socialist economy, they just don’t know it’s called that. Thanks to Fox News Newspeak, they use all the wrong words for things. There is no word in their heads for what they want, so they express their extreme discontent and social and economic insecurity by symbolic protest (and misuse of another, less innocent term).
People are becoming radicalized by the economy and they could go either way. Obviously, I would prefer it if the left won, and so would most of the people throwing Lipton around. There used to be a quite popular flyer that listed all the stuff you could buy for the cost of a single stealth bomber. Hundreds of schools, hospitals, etc. Well, what could you buy for trillions of dollars? How many YEARS of universal healthcare? How many bridges could be rebuilt, giving people jobs and making roads safer? You see where I’m going, but instead of just listing the object that would be there at the end, also mention the means. Workers build those projects. Workers like the folks at the rallies.
The financial sector is fucked to be sure, but we didn’t get out of the Great Depression by giving money to banks, we got out of it through a massive government spending program. Rather than a devastating war, we could rebuild our crumbling infrastructure. Giving these folks the security and employment they need is also the key to fixing the economy. But this plan does not widen the gap between rich and poor, so it’s not on the agenda and it won’t be until protests force it to be. This could be the germ of change. Stop snickering and start a conversation!

more performance stuff

vincent rioux is now talking about his work with sc

he improvised with an avant sort of theatre company. The video documentation was cool. I didn’t know about events like this in paris. Want to know more.

in another project, he made very simple controllers with arduino inside. He had 6 controllers. One arduino for all 6.

Tiny speakers. This is also nifty. Used it at Pixelache festival.

the next project uses a light system. Uses a hypercube thing. Which is a huge thing that the dancer stands inside. Sc controls it.

the next thing is a street performance asking folks to help clean the street. Part of festival mal au pixel. This is mental! Also, near where i used to live. Man, i miss paris sometimes.

the next ne is a crazy steam punk dinner jacket. With a wiimote thing.

dan’s installation

dan st. Clair is talking about his awesome instillation which involves speakers hangong from trees doing bird like rendition of ‘like a virgin’, which is utterly tweaking out the local mocking birds.

when he was an undergrad he did a nifty project with songs stuck in people’s heads. It was conxeptual and not musical.

when he lived in chicago he did a map of muzak in stores on state street, including genre and de;ivery .ethod. He made a tourist brochure with muzak maps and put them in visitor centers.

he’s interested in popular music in environemtnal settings

max neuhaus did an unmarked, invisible sounds installation in time square. Dan dug the sort of invisible, discovery aspect.

his bird e.ulator is solar powered. Needs no cables. Has an 8bit microcontroller. They’re cheap as hell.

he’s loaded frequncy envelopes in memory. Fixed control rate. Uses a single wavetable oscillator httP://www.myplace.nu/avr/minidds/index.htm

he made recordings of birds and extracted the partials.

he throws this up into trees. However, neighbors got annoyed and called the cops or destroyed the speakers.

he’s working on a new version which is in close proximity to houses. He’s adding a calddendar to shut it down sometimes and amplitude controls.

he has an IFF class to deal with sdif and midi files. SDIFFrames class works with these files.

there’s some cool classes for fft, like FFTPeaks

he’s written some cool guis for finding partials.

his method of morphing between bird calls and pop songs is pretty brilliant.

dan is awesome

live video

sam pluta wrote some live video software. It’s inspired by glitchbot, meapsoft

glitchbot records sequnces and loops and stutters them. Records 16 bar phrase and loops and tweaks it. I think i have seen this. It can add beats and do subloops, etc

the sample does indeed sound glitchy

probability control can be clumsy in live performance. Live control of beats is hard.

MEAPSoft does reordering.

his piece from the last symposium used a sample bank which he can interpret and record his interpretting and then do stuff with that. So there are two layers of improvisation. It has a small initial parameter space nad uses a little source to make a lot of stuff.

i remember his pice from last time

what he learned from that was that it was good, especially for noisy music. And he controlled it by hitting a lot of keys which was awesome

he wrote an acoustic oiece using sound block. Live instruments can do looping differently, you can make the same note longer.

so he wrote michel chion’s book on film and was influenced. He started finding sound moments in films. And decided to use them for source material.

sci-fi films have the best sound, he says.

playing a lot of video clips in fast succession is hard, because you need a format that renders single frames quickly. Pixlet format is good for that.

audio video synch is hard with quicktime, so he loaded audio into sc and did a bridge to video with quartz composer.

qc is efficient at rendering

he wanted to make noisy loops, like to change them. You can’t buffer video loops in the same way, so he needed to create metaloops of playback information. So looped data.

a loop contains pointers to movies clips, but starts from where he last stopped. Which sounds right

he organized the loops by category, kissing, car chases, drones,etc

this is an interesting way of organizing and might help my floundering blake piece.

he varies loop duration based on the section of the piece.

live blog : beast mulch

Scott is talking about beast mulch, which is still unreleased,
there are calsses for controllers, like hardware. There’s a plugin framework to easily extend stuff. BMPulginSpec(‘name’, {|this| etc. . . .

multichannel stuff and swarm granulation, etc.

kd tree class finds closest speaker neighbor

if you want beastmulch, get it from scott’s website

there’s speaker classes, BMSpeaker

BMInOutArray does associations.

beast mulch is a big library for everyone. Everything must be named. There are time references, like a soundflile player;

trying to be adaptible. 100 channels or 8, make it work on both. Supports jit and stems.

a usage example: can be used live. Routing table, control matrixes. Pre and post processing use plugins

i NEED to download this & use it.

http://scottwilson.ca

http://www.beast.bham.ac.uk/research/mulch.shtml

. . .