Introduction

Ajeeb is a set of design patterns and tools that aid in the construction of games, installations, media art, and other interactive software that I affectionately call playful systems.

It is the result of over a decade and a half of my experience building these systems both in commercial and artistic capacities, and an equivalent amount of time searching for a sense of fluency and flow with digital tools that felt stifling and badly matched to the task of artistic expression. I feel very strongly that I have found the semantics I have been looking for and implementations of those semantics in conventional well supported software platforms. They are placed in the public domain in the hopes that they may be helpful to others either directly as tools or indirectly as objects of study.

Ramsey Nasser

History

Playful Systems

Patterns and Engines

Chapter 1

Test

export default function* (SCHED, INPUT, showUI = false) {
    const melodySynth = new Tone.PolySynth(Tone.Synth, {
        envelope: {
            attack: 0.2,
            release: 0.1
        }
    })

    const droneSynth = new Tone.Player(assets.audio.blackBoxDrone)

    const vib = new Tone.Vibrato(0, 0.000007070506370279221)
    const filter = new Tone.Filter(1111, 'bandpass')
    filter.Q.value = 1
    filter.detune.value = 0
    const chorus = new Tone.Chorus(1, 2.5, 6)
    const delay = new Tone.FeedbackDelay(0, 0)
    const reverb = new Tone.Reverb(1.5)
    const gain = new Tone.Gain(2)
    const compressor = new Tone.Compressor(-30, 3)
    const pan = new Tone.Panner()
    melodySynth.connect(vib)
    droneSynth.connect(vib)
    vib.connect(filter)
    filter.connect(delay)
    delay.connect(reverb)
    reverb.connect(chorus)
    chorus.connect(gain)
    gain.connect(compressor)
    compressor.connect(pan)
    pan.toDestination()

    try {
        while (!reverb.ready) yield
        yield* interact(INPUT, vib, pan, melodySynth, droneSynth)
    } finally {
        SCHED.add(function* () {
            gain.gain.linearRampTo(0, 1)
            yield* coro.seconds(1)
            vib.disconnect()
            chorus.disconnect()
            delay.disconnect()
            reverb.disconnect()
            gain.disconnect()
        })
    }
}

Chapter P

Chapter 1

Test

export default function* (SCHED, INPUT, showUI = false) {
    const melodySynth = new Tone.PolySynth(Tone.Synth, {
        envelope: {
            attack: 0.2,
            release: 0.1
        }
    })

    const droneSynth = new Tone.Player(assets.audio.blackBoxDrone)

    const vib = new Tone.Vibrato(0, 0.000007070506370279221)
    const filter = new Tone.Filter(1111, 'bandpass')
    filter.Q.value = 1
    filter.detune.value = 0
    const chorus = new Tone.Chorus(1, 2.5, 6)
    const delay = new Tone.FeedbackDelay(0, 0)
    const reverb = new Tone.Reverb(1.5)
    const gain = new Tone.Gain(2)
    const compressor = new Tone.Compressor(-30, 3)
    const pan = new Tone.Panner()
    melodySynth.connect(vib)
    droneSynth.connect(vib)
    vib.connect(filter)
    filter.connect(delay)
    delay.connect(reverb)
    reverb.connect(chorus)
    chorus.connect(gain)
    gain.connect(compressor)
    compressor.connect(pan)
    pan.toDestination()

    try {
        while (!reverb.ready) yield
        yield* interact(INPUT, vib, pan, melodySynth, droneSynth)
    } finally {
        SCHED.add(function* () {
            gain.gain.linearRampTo(0, 1)
            yield* coro.seconds(1)
            vib.disconnect()
            chorus.disconnect()
            delay.disconnect()
            reverb.disconnect()
            gain.disconnect()
        })
    }
}

Chapter 1

Test

export default function* (SCHED, INPUT, showUI = false) {
    const melodySynth = new Tone.PolySynth(Tone.Synth, {
        envelope: {
            attack: 0.2,
            release: 0.1
        }
    })

    const droneSynth = new Tone.Player(assets.audio.blackBoxDrone)

    const vib = new Tone.Vibrato(0, 0.000007070506370279221)
    const filter = new Tone.Filter(1111, 'bandpass')
    filter.Q.value = 1
    filter.detune.value = 0
    const chorus = new Tone.Chorus(1, 2.5, 6)
    const delay = new Tone.FeedbackDelay(0, 0)
    const reverb = new Tone.Reverb(1.5)
    const gain = new Tone.Gain(2)
    const compressor = new Tone.Compressor(-30, 3)
    const pan = new Tone.Panner()
    melodySynth.connect(vib)
    droneSynth.connect(vib)
    vib.connect(filter)
    filter.connect(delay)
    delay.connect(reverb)
    reverb.connect(chorus)
    chorus.connect(gain)
    gain.connect(compressor)
    compressor.connect(pan)
    pan.toDestination()

    try {
        while (!reverb.ready) yield
        yield* interact(INPUT, vib, pan, melodySynth, droneSynth)
    } finally {
        SCHED.add(function* () {
            gain.gain.linearRampTo(0, 1)
            yield* coro.seconds(1)
            vib.disconnect()
            chorus.disconnect()
            delay.disconnect()
            reverb.disconnect()
            gain.disconnect()
        })
    }
}

Chapter 1

Test

export default function* (SCHED, INPUT, showUI = false) {
    const melodySynth = new Tone.PolySynth(Tone.Synth, {
        envelope: {
            attack: 0.2,
            release: 0.1
        }
    })

    const droneSynth = new Tone.Player(assets.audio.blackBoxDrone)

    const vib = new Tone.Vibrato(0, 0.000007070506370279221)
    const filter = new Tone.Filter(1111, 'bandpass')
    filter.Q.value = 1
    filter.detune.value = 0
    const chorus = new Tone.Chorus(1, 2.5, 6)
    const delay = new Tone.FeedbackDelay(0, 0)
    const reverb = new Tone.Reverb(1.5)
    const gain = new Tone.Gain(2)
    const compressor = new Tone.Compressor(-30, 3)
    const pan = new Tone.Panner()
    melodySynth.connect(vib)
    droneSynth.connect(vib)
    vib.connect(filter)
    filter.connect(delay)
    delay.connect(reverb)
    reverb.connect(chorus)
    chorus.connect(gain)
    gain.connect(compressor)
    compressor.connect(pan)
    pan.toDestination()

    try {
        while (!reverb.ready) yield
        yield* interact(INPUT, vib, pan, melodySynth, droneSynth)
    } finally {
        SCHED.add(function* () {
            gain.gain.linearRampTo(0, 1)
            yield* coro.seconds(1)
            vib.disconnect()
            chorus.disconnect()
            delay.disconnect()
            reverb.disconnect()
            gain.disconnect()
        })
    }
}

Chapter 1

Test

export default function* (SCHED, INPUT, showUI = false) {
    const melodySynth = new Tone.PolySynth(Tone.Synth, {
        envelope: {
            attack: 0.2,
            release: 0.1
        }
    })

    const droneSynth = new Tone.Player(assets.audio.blackBoxDrone)

    const vib = new Tone.Vibrato(0, 0.000007070506370279221)
    const filter = new Tone.Filter(1111, 'bandpass')
    filter.Q.value = 1
    filter.detune.value = 0
    const chorus = new Tone.Chorus(1, 2.5, 6)
    const delay = new Tone.FeedbackDelay(0, 0)
    const reverb = new Tone.Reverb(1.5)
    const gain = new Tone.Gain(2)
    const compressor = new Tone.Compressor(-30, 3)
    const pan = new Tone.Panner()
    melodySynth.connect(vib)
    droneSynth.connect(vib)
    vib.connect(filter)
    filter.connect(delay)
    delay.connect(reverb)
    reverb.connect(chorus)
    chorus.connect(gain)
    gain.connect(compressor)
    compressor.connect(pan)
    pan.toDestination()

    try {
        while (!reverb.ready) yield
        yield* interact(INPUT, vib, pan, melodySynth, droneSynth)
    } finally {
        SCHED.add(function* () {
            gain.gain.linearRampTo(0, 1)
            yield* coro.seconds(1)
            vib.disconnect()
            chorus.disconnect()
            delay.disconnect()
            reverb.disconnect()
            gain.disconnect()
        })
    }
}

Chapter 1

Test

export default function* (SCHED, INPUT, showUI = false) {
    const melodySynth = new Tone.PolySynth(Tone.Synth, {
        envelope: {
            attack: 0.2,
            release: 0.1
        }
    })

    const droneSynth = new Tone.Player(assets.audio.blackBoxDrone)

    const vib = new Tone.Vibrato(0, 0.000007070506370279221)
    const filter = new Tone.Filter(1111, 'bandpass')
    filter.Q.value = 1
    filter.detune.value = 0
    const chorus = new Tone.Chorus(1, 2.5, 6)
    const delay = new Tone.FeedbackDelay(0, 0)
    const reverb = new Tone.Reverb(1.5)
    const gain = new Tone.Gain(2)
    const compressor = new Tone.Compressor(-30, 3)
    const pan = new Tone.Panner()
    melodySynth.connect(vib)
    droneSynth.connect(vib)
    vib.connect(filter)
    filter.connect(delay)
    delay.connect(reverb)
    reverb.connect(chorus)
    chorus.connect(gain)
    gain.connect(compressor)
    compressor.connect(pan)
    pan.toDestination()

    try {
        while (!reverb.ready) yield
        yield* interact(INPUT, vib, pan, melodySynth, droneSynth)
    } finally {
        SCHED.add(function* () {
            gain.gain.linearRampTo(0, 1)
            yield* coro.seconds(1)
            vib.disconnect()
            chorus.disconnect()
            delay.disconnect()
            reverb.disconnect()
            gain.disconnect()
        })
    }
}

Chapter 1

Test

export default function* (SCHED, INPUT, showUI = false) {
    const melodySynth = new Tone.PolySynth(Tone.Synth, {
        envelope: {
            attack: 0.2,
            release: 0.1
        }
    })

    const droneSynth = new Tone.Player(assets.audio.blackBoxDrone)

    const vib = new Tone.Vibrato(0, 0.000007070506370279221)
    const filter = new Tone.Filter(1111, 'bandpass')
    filter.Q.value = 1
    filter.detune.value = 0
    const chorus = new Tone.Chorus(1, 2.5, 6)
    const delay = new Tone.FeedbackDelay(0, 0)
    const reverb = new Tone.Reverb(1.5)
    const gain = new Tone.Gain(2)
    const compressor = new Tone.Compressor(-30, 3)
    const pan = new Tone.Panner()
    melodySynth.connect(vib)
    droneSynth.connect(vib)
    vib.connect(filter)
    filter.connect(delay)
    delay.connect(reverb)
    reverb.connect(chorus)
    chorus.connect(gain)
    gain.connect(compressor)
    compressor.connect(pan)
    pan.toDestination()

    try {
        while (!reverb.ready) yield
        yield* interact(INPUT, vib, pan, melodySynth, droneSynth)
    } finally {
        SCHED.add(function* () {
            gain.gain.linearRampTo(0, 1)
            yield* coro.seconds(1)
            vib.disconnect()
            chorus.disconnect()
            delay.disconnect()
            reverb.disconnect()
            gain.disconnect()
        })
    }
}

Chapter 1

Test

export default function* (SCHED, INPUT, showUI = false) {
    const melodySynth = new Tone.PolySynth(Tone.Synth, {
        envelope: {
            attack: 0.2,
            release: 0.1
        }
    })

    const droneSynth = new Tone.Player(assets.audio.blackBoxDrone)

    const vib = new Tone.Vibrato(0, 0.000007070506370279221)
    const filter = new Tone.Filter(1111, 'bandpass')
    filter.Q.value = 1
    filter.detune.value = 0
    const chorus = new Tone.Chorus(1, 2.5, 6)
    const delay = new Tone.FeedbackDelay(0, 0)
    const reverb = new Tone.Reverb(1.5)
    const gain = new Tone.Gain(2)
    const compressor = new Tone.Compressor(-30, 3)
    const pan = new Tone.Panner()
    melodySynth.connect(vib)
    droneSynth.connect(vib)
    vib.connect(filter)
    filter.connect(delay)
    delay.connect(reverb)
    reverb.connect(chorus)
    chorus.connect(gain)
    gain.connect(compressor)
    compressor.connect(pan)
    pan.toDestination()

    try {
        while (!reverb.ready) yield
        yield* interact(INPUT, vib, pan, melodySynth, droneSynth)
    } finally {
        SCHED.add(function* () {
            gain.gain.linearRampTo(0, 1)
            yield* coro.seconds(1)
            vib.disconnect()
            chorus.disconnect()
            delay.disconnect()
            reverb.disconnect()
            gain.disconnect()
        })
    }
}