Skip to content

Instantly share code, notes, and snippets.

@srikumarks
Last active August 29, 2015 14:05
Show Gist options
  • Save srikumarks/280edda1d023b1183168 to your computer and use it in GitHub Desktop.
Save srikumarks/280edda1d023b1183168 to your computer and use it in GitHub Desktop.
Functional frequency modulation ...
// Here is a possible pure-functional implementation of stateful signals.
function makeSound(signal, currState, result, endCondition) {
return endCondition(currState) ? reverse(result, null) : signal(currState, function (nextState, val) {
return makeSound(signal, nextState, pair(val, result), endCondition);
});
}
// A simple implementation of pair
function pair(val, list) {
return {head: val, tail: list};
}
function reverse(list, tail) {
return list ? reverse(list.tail, pair(list.head, tail)) : tail;
}
// So a signal is a function that takes a “state” as arg1 and a continuation function
// as arg2 ... which itself takes a state as arg1 and a value as arg2.
// Here is a proper sine wave using this scheme -
// 'freq' itself is a signal that can change over time.
function sine(freq) {
return function (state, sink) {
return freq(state, function (state, val) {
var next = (state || 0) + val * dt; // dt is a global constant = 1/sampling_rate.
return sink(next, Math.sin(2 * Math.PI * next));
});
};
}
// Here is a way to combine two signals using a binary function -
function combine(func, sig1, sig2) {
return function (state, sink) {
return sig1(state[0], function (state1, v1) {
return sig2(state[1], function (state2, v2) {
return sink([state1, state2], func(v1,v2));
});
});
};
}
// … and some sample functions defined using them -
function plusOp(a,b) { return a+b; }
function mulOp(a,b) { return a*b; }
function add(sig1, sig2) {
return combine(plusOp, sig1, sig2);
}
function mul(sig1, sig2) {
return combine(mulOp, sig1, sig2);
}
function konst(k) {
return function (state, sink) {
return sink(state, k);
};
}
// After all that, comes the first recursive higher order function -
// a set of evenly spaced harmonics that can be frequency modulated.
function harmonics(freq, n) {
if (n === 0) {
return konst(0);
}
return add(sine(mul(freq, konst(n))), harmonics(freq, n-1));
}
// Signal processing folks will cringe at the mountain of inefficiencies here ;)
// … but it does give the ability to abstract stateful signals. If you want to,
// you can thread something like “current_time” through the state argument.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment