Betablocker DS code patterns (part 1)

2012.01.27

Some useful Betablocker DS code patterns as used in common live coding situations.

Firstly, when carrying out a sound check before a live performance it's important to keep some kinds of sound engineers happy generating as many different sounds as you can so they can fiddle around with stuff - of course remember to turn everything up to 8 when asked to make the loudest sound you can in order to leave some overhead to blow the PA.

This is a betablocker program which will play all the sounds in a sound bank at all frequencies. Add more concurrent threads to make it more interesting. Values interpreted as pointers are visualised as arrows:


(the instruction set description can be found here)

In betablocker the beat is always locked to the instruction cycle rate, so fast changing sounds are a matter of optimisation. One of the most common ways around this (and a good way to start things off in a gig) is to use one fast loop program for playing sounds while another slower program modifies the first by overwriting bits of it.

More to follow in this series. See also evolved betablocker genetic programs.

Categories : howto   livecoding   visual programming

Two talks in Helsinki

2011.11.05

Next week I'm presenting Naked on Pluto at Pixelache's Pixelversity on Wednesday evening (9th November) at the Cable Factory. Owen Kelly will also be there to talk about Pixelversity's ‘Social Identity, Augmented Reality & Virtuality’ Study Group' which will take place next year.

On Saturday afternoon (12th November), Till Bovermann and I will be demoing Supercollider, Fluxus, Scheme Bricks and Betablocker DS and talking about what it means to be a livecoder at the Hacklab Helsinki.

Betablocker rehersal

2011.10.22
Categories : homebrew   livecoding

slub in Paris

2011.10.04

Some random pictures from some excellent (and at times very loud) few days in Paris. Thanks to Sony Computer Science Labs and also the Paris contingent of the TPOLM demo crew for coming out to support us.

The gig was extensively recorded, so hopefully more about this soon.

Categories : gig   livecoding   slub

BetaBlocker DS test tones

2011.09.14

After a week of heavy development on Germination X, and with a fast approaching performance, it seemed the time to dive back into Gameboy DS homebrew and get the bits and pieces of assembler code I'd been playing with together into something I could build more sounds from.

After getting the low level stuff working properly, I got busy making a bunch of audio scenes that I can trigger from Betablocker DS code.


Sounds hosted by archive.org

Mostly I'm doing wavetable based things, with lots of frequency and ring modulation. I was also pleased to find this simple resonant filter thanks to the ever fabulous musicdsp archive (and thanks to Paul Kellett for originally posting it):

// set feedback amount given f and q between 0 and 1
fb = q + q/(1.0 - f);

// for each sample...
buf0 = buf0 + f * (in - buf0 + fb * (buf0 - buf1));
buf1 = buf1 + f * (buf0 - buf1);
out = buf1;

The next step was to read Jasper Vijn's excellent explanation of fixed point maths which I've used a bit on the Android but not really totally understood before. Mobile devices tend to only have integer maths at the hardware level, so if we restrict the calculations to fixed point it's much faster and kinder to batteries than the floating point equivalent. Here is the fixed point version of the filter:

// we are using .10 fixed point (10 bits for the fractional part)
#define FX_SHIFT 10

// convert an int into to it's fixed representation
inline s32 fx(s32 i) { return i<<FX_SHIFT; }

// multiply two fixed point numbers (returns fixed point)
inline s32 fxmul(s32 a, s32 b) { return (a*b)>>FX_SHIFT; }

// f is cutoff frequecy, q is resonance, s is the filter state
void lpf(s16* dst, s16* src, u32 length, s16 f, s16 q, s16 *s)
{
    u32 fb = q+fxmul(q,fx(1)-f);
    for (u32 i=0; i<length; ++i)
    {
        s[0]+=fxmul(f,src[i]-s[0]+fxmul(fb,s[0]-s[1]));
        s[1]+=fxmul(f,s[0]-s[1]);
        dst[i]=s[1];
    }
}
Categories : homebrew   livecoding

Missile Command machinima in São Paulo

2011.08.30

Some images of the Machinima exhibition at FILE 2011 in São Paulo, featuring a movie of a livecoded abstractification of a Missile Command game written/performed/destroyed/recorded in Fluxus.

Categories : fluxus hacking   games   livecoding

Betablocker DS: Table feedback after Claudius Maximus

2011.08.29

After getting some dates for gigs with Betablocker DS, I am spending some time looking into audio algorithms, and implementing them on the Gameboy DS. Last Thursday I spent some time at the TAI studio/bunker with Till Bovermann investigating these PD patches by Claudius Maximus:

The algorithm uses feedback to create sounds that take some time to play through a wide range of frequencies. It works by writing into the same buffer it's playing, but at a different rate/position - the resulting ugliness suits the style of BBDS very much. As an aid to our understanding Till converted the algorithm to Supercollider, then over the next couple of days I managed to get it running with an inner loop of 9 instructions on the DS (could probably be optimised further, but I'm still a beginner):

@ ----------------------------------------------------
@ qrz_maximus: *dst, length, readpos, writepos [freq, *tab]
@ ----------------------------------------------------
        .global qrz_maximus
	.type   qrz_maximus, %function
qrz_maximus:
        push    {r4,r5,r6,r7}       @ push the registers we need
        ldr     r4, [r13,#20]       @ load freq from stack into r4
        ldr     r5, [r13,#24]       @ load *tab from stack into r5
        ldr     r6, .tablength      @ load the tablen into r6
.maximus_loop:
        ldrh    r7, [r5,r2]         @ load the sample into r7
        strh    r7, [r0], #2        @ write output: *dst=r7 dst++
        strh    r7, [r5,r3]         @ feedback into tab[writepos]=r7
        add     r2, r2, r4          @ readpos+=freq
        and     r2, r2, r6          @ mask readpos into range
        add     r3, r3, #2          @ writepos++
        and     r3, r3, r6          @ mask writepos into range
        subs    r1, r1, #1          @ length--
        bne     .maximus_loop       @ repeat until length zero
        mov     r0, r2              @ return readpos
        pop     {r4,r5,r6,r7}
        bx      lr                  @ exit
.tablength:
        .word   0x00003FF

And here it is running on autopilot with a test program in Betablocker:

Golden Medallions and in-game programming

2011.07.11

Once the low level code for a Naked on Pluto bot is written in Scheme, it's added by the game using secret commands which program the game inside itself, while it's running. This means the game can be changed while people are playing it - which makes it much easier to add new things without worrying about the disruption caused by restarting the server. We can also work on the game collaboratively, at the same time this way.


(Programming a spybot with it's behaviour)

Eventually the plan is to be able to program the bots fully within the game client - this is still a long term goal, but there are of course some fairly complex security problems with this idea.


(dressing a AudienceBot with another object)

Not all players have the ability to use these secret commands right now, in order to access them a player has to be carrying a special object (also known as a "Golden Medallion"). This allows you access to all areas of the game, including an "administration room" and various other secret powers.

Categories : livecoding   naked on pluto

Rainy sunday

2011.05.29

A rainy Sunday, with only the dog for company, so in between walks I thought I'd try and learn some assembler. I've been unhappy with triggering samples with Betablocker DS (I prefer synthesis) and I've heard good things about ARM asm - so it seemed like a good opportunity to attempt a small, fast and dirty synth.

I found some really nice tutorials here and here. I've done a tiny bit of this sort of thing before with microcontrollers, but this is a more of a respectable flavour of assembler, on a decent RISC processor (which derives from the Acorn Archimedes and is now used on IPhones, Androids and Gameboys). Here is a white noise generator:

; white_noise(r0=*dst, r1=clock, r2=length, r3=freq)
white_noise:
        push    {r4,r5,r6}          ; need to restore registers we use
        mov     r4, r1              ; r4 is the rand state (start with clock)
        ldr     r5, .rnd_data       ; r5 is the multiplier value
        ldr     r6, .rnd_data+1     ; r6 is the addition value
.noise_loop:
        mla     r4, r5, r4, r6      ; the maths bit: r4 = (r6 + (r5 * r4))
        strh    r4, [r0], #2        ; *dst++ = clock; 
        subs    r2, r2, #1          ; length--;
        bne     .noise_loop         ; branch if length not zero
        pop     {r4,r5,r6}
        bx      lr                  ; return
.rnd_data:
        .word   0x000343FD          ; nicked from ansi c rand()
        .word   0x00269EC3          ; need to keep large numbers (>8bit) as data

This code is based on the ansi C rand() function that basically looks like this:

randnum = randnum * 214013 + 2531011;

Which we can do in a single instruction - mla (multiply with accumulate). Of course, gcc would presumably optimise much better code than mine from C++, but there is something more satisfying about doing it this way. I certainly prefer the sound - and over half the cpu usage remains unused with 5 voices and the interface running. The rest of the code is here.

Betablocker machine running on Supercollider

2011.05.10

Is seems our meetings at the TAI studio are bearing fruit already, Till Bovermann has ported the Betablocker machine as a Supercollider UGen. What's interesting is rather than taking a similar approach to music making, this version is running at audio rate and the processes directly generate sample data. He can also run lots of them at the same time and control them from SCLang. It's great when people use your code, but even better when it gets used in ways you didn't think about.

Categories : livecoding