Recamán 🧮

A 'spooky' audio representation the Recamán sequence shown in Numberphile youtube.com/watch?v=fgc5tdiit9u&t=438s

Visual representation: turtletoy.net/turtle/4874a9d70b

Log in to post a comment.

//
// You can find the Dittytoy API Reference here: https://Dittytoy.net/syntax
// Example ditties can be found here: https://dittytoy.net/user/Dittytoy
//
// Most of your ditty will run 44100 times per second using javascript in the browser.
// Make sure you optimize your ditty to work well on as many devices as possible. To do that, try to limit
// the number of simultaneously active synths: make sure they don't last longer than necessary, or you can
// hear them, and spread them over different loops (each loop runs in a separate worker).
//

ditty.bpm = 120;
input.octaveBase = 4; //min=-1, max=9, step=1
input.octaveReach = 3; //min=1, max=10, step=1
input.use = 0; //min=0, max=4, step=1 (All keys (like Numberphile did), All but the black keys, Only the black keys, C-major, C-minor)
const availableNoteSets = [Array.from({length: 12}).map((v, i) => i), [0, 2, 4, 5, 7, 9, 11], [1, 3, 6, 8, 10], [0, 4, 7], [0, 3, 7]];
const iterator = recaman();
loop( () => {
    const recamanValue = iterator.next().value;
    const octave = input.octaveBase + (((recamanValue/availableNoteSets[input.use].length)|0)%input.octaveReach);
    const noteInOctave = availableNoteSets[input.use][recamanValue%availableNoteSets[input.use].length];
    
    sine.play(octave*12 + noteInOctave, { attack: 0.01, release: 0.25,  duration: 0.25, pan: Math.random() - .5, amp: 1.0 });
    sleep( 0.35 );

}, { name: 'Recamán' });

function* recaman(skip = 0, take = 0) {
    const sequence = [0];
    for(let i = 1; take==0||i<skip+take+1; i++) {
        if(i > skip) yield sequence[i - 1];
        [sequence[i-1]-i].forEach(next => sequence.push(next > 0 && !sequence.includes(next)? next: sequence[i-1]+i));
    }
}