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.
Leave a Reply