Moodler: A Digital Modular Synthesiser with an Analogue User - - PowerPoint PPT Presentation

moodler a digital modular synthesiser with an analogue
SMART_READER_LITE
LIVE PREVIEW

Moodler: A Digital Modular Synthesiser with an Analogue User - - PowerPoint PPT Presentation

Moodler: A Digital Modular Synthesiser with an Analogue User Interface Dan Piponi Two starting points Number 1: LittleBits Synth Kit As a Physically-embodied, Domain Specific Functional Programming Language Noble, James and Jones,


slide-1
SLIDE 1

Moodler: A Digital Modular Synthesiser with an Analogue User Interface

Dan Piponi

slide-2
SLIDE 2

Two starting points

Number 1: LittleBits Synth Kit As a Physically-embodied, Domain Specific Functional Programming Language
 Noble, James and Jones, Timothy.

slide-3
SLIDE 3

Two starting points

Number 2:

slide-4
SLIDE 4

Let’s dive in…

  • Standard synth example (demo_test_full_synth)
  • Stand alone multisaw example (test_demo_multisaw)
slide-5
SLIDE 5

Let’s dive in…

  • Physical and virtual user interfaces
  • Cables and knobs
  • MIDI
  • OSC
  • GUI written entirely in Haskell
  • Back end written almost entirely in Haskell

generating, compiling and linking C code on fly.

slide-6
SLIDE 6

Overview

Mock Modular

UI Moodler

MIDI-OSC Bridge USB/ Serial-OSC Bridge

slide-7
SLIDE 7

Decisions, decisions…

  • Want to exploit existing libraries
  • Want graphic user interface
  • Want to talk various protocols: USB/Serial, MIDI
  • Want fast generation and compilation of fast code
slide-8
SLIDE 8

Code Structure

Moodler

GUI plugins Audio plugins

Shared library

UI

slide-9
SLIDE 9

Haskell

  • I can program in it
  • Great fit for code generation, FFI, dlopen, C parser and

representation, GHC accessible through library.

  • Don’t quite trust it for devices other than network. But

OSC rests on TCP/IP so delegate MIDI and USB/Serial to external applications and audio to C.

  • Not convinced by existing GUI offerings but I don’t

mind drawing everything myself: gloss. Not perfect fit but does what it promises well.

slide-10
SLIDE 10

C

  • I can program in it
  • If I used LLVM I’d still need to write a compiler to

generate LLVM. I think of clang as an API to generate LLVM.

  • Plenty of existing C audio code to borrow.
  • I want to eventually generate standalone but hackable

code for microcontrollers.

slide-11
SLIDE 11

Code Structure

Moodler

GUI plugins Audio plugins

Shared library

UI

Haskell C Haskell Haskell C

slide-12
SLIDE 12

.msl Plugins

double result; void init() { } void fini() { } inline void exec(in __attribute__((normal(1.0))) control cv, in sample signal,

  • ut sample result) {

result = cv*signal; }

slide-13
SLIDE 13

.msl Plugins

double result; void init() { } void fini() { } inline void exec(in __attribute__((normal(1.0))) control cv, in sample signal,

  • ut sample result) {

result = cv*signal; }

slide-14
SLIDE 14

.hs Plugins

do plane <- currentPlane p <- mouse panel <- container' "panel_2x1.png" p (Inside plane) lab <- label' "vca" (p+(-36.0,84.0)) (Outside panel) name <- new' "vca" inp <- plugin' (name ! "cv") (p+(-24,24)) (Outside panel) setColour inp "#control" inp <- plugin' (name ! "signal") (p+(-24,-24)) (Outside panel) setColour inp "#sample"

  • ut <- plugout' (name ! "result") (p+(24,0)) (Outside panel)

setColour out "#sample" recompile return ()

slide-15
SLIDE 15

A minimal synth

slide-16
SLIDE 16

Generated C code

void execute(struct State * state, double * buffer) { for (int i = 0; i < 256; ++i) { state->id5.result = state->input13.result; state->id12.result = state->input19.result; state->sum21.result = state->id5.result + state->id12.result; state->id7.result = 0; audio_saw_exec(state->sum21.result, state->id7.result, &state->audio_saw1); state->id10.result = state->audio_saw1.result; adsr_exec(state->input15.result, state->input16.result, state->input18.result, state->input17.result, state->input20.result, &state->adsr0); state->vca22.result = state->adsr0.result * state->id10.result; buffer[2 * i] = state->vca22.result + 0; buffer[2 * i + 1] = state->vca22.result + 0; } }

slide-17
SLIDE 17

From .msl…

double last_up; double last_down; double multiplier_up; double multiplier_down; double result; void init() { last_up = -1.0; last_down = -1.0; } void exec(in control decay_up, in control decay_down, in control input, out control result) { if (result > input) { if (decay_down != last_down) { multiplier_down = exp(-dt/max(0.001, decay_down)); } result = input+multiplier_down*(result-input); last_down = decay_down; } else if (result < input) { if (decay_up != last_up) { multiplier_up = exp(-dt/max(0.001, decay_up)); } result = input-multiplier_up*(input-result); last_up = decay_up; } }

slide-18
SLIDE 18

…to C

void vactroid_exec(double decay_up, double decay_down, double input, struct vactroid * vactroid) { if (vactroid->result > input) { if (decay_down != vactroid->last_down) { vactroid->multiplier_down = exp(-dt / max(0.001, decay_down)); } vactroid->result = input + vactroid->multiplier_down * (vactroid->result - input); vactroid->last_down = decay_down; } else if (vactroid->result < input) { if (decay_up != vactroid->last_up) { vactroid->multiplier_up = exp(-dt / max(0.001, decay_up)); } vactroid->result = input - vactroid->multiplier_up * (input - vactroid->result); vactroid->last_up = decay_up; } }

slide-19
SLIDE 19

UI Control Flow

OS/GUI User Code

Callback Callback Return Return

OS/GUI User Code

Return Return Call Call

slide-20
SLIDE 20

Reinversion of Control

do e <- getEvent case e of … …do stuff …

Two approaches

do e <- getEvent case e of … …do stuff …

getEvent getEvent getEvent

This continuation is established as a callback and control is relinquished to GUI Free monad builds tree. Semantics provided by interpreter that runs a small step at a time in callback. Another free monad is also used for .hs plugin to get complete separation

  • f plugin code from

Moodler internals.

slide-21
SLIDE 21

Recognising cables

Each output has unique square wave signal

slide-22
SLIDE 22

Permutations with Cables

U

delay delay delay delay

slide-23
SLIDE 23

Permutations with Cables

U

Householder Reflection

slide-24
SLIDE 24

Permutations with Cables

slide-25
SLIDE 25

Live code?

  • Or maybe a canned example (demo_test_bitwise)
slide-26
SLIDE 26

Thanks

  • Barnaby Robson for porting to

PortAudio and Oscilloscope.