Last active
March 12, 2022 18:12
-
-
Save catfact/feb365921d7f6dace86e587795daaf3d to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// u-law | |
( | |
Routine { s = Server.default.waitForBoot; | |
// this N determines lookup table resolution | |
n = 512; | |
~unit = Array.fill(n, {|i| i.linlin(0, n-1, -1, 1) }); | |
/////////////////////////////// | |
//// main bit of mu-law | |
~mu = 255; | |
~compress_curve = ~unit.collect({ |x| | |
x.sign * log(1 + (~mu * x.abs)) / log(1 + ~mu); | |
}); | |
~expand_curve = ~unit.collect({ |y| | |
y.sign / ~mu * ((1+~mu)**(y.abs) - 1); | |
}); | |
/////////////////////////////// | |
{ | |
~compress_curve.plot; | |
~expand_curve.plot; | |
}.defer; | |
// blah blah get the curves into Buffers | |
~compress_buf = Buffer.loadCollection(s, Signal.newFrom(~compress_curve).asWavetableNoWrap); | |
~expand_buf = Buffer.loadCollection(s, Signal.newFrom(~expand_curve).asWavetableNoWrap); | |
b = Bus.audio(s, 1); | |
~sine = { arg hz=110, amp=1; | |
Out.ar(b.index, amp.lag(0.1) * SinOsc.ar(hz)) | |
}.play(s); | |
~adc = { arg in=0, amp=1; | |
Out.ar(b.index, amp.lag(0.1) * SoundIn.ar(in)) | |
}.play(s); | |
s.sync; | |
~crush = { | |
arg steps = 256, compAmt=1, expAmt=1; | |
var src, comp, x, crush, exp; | |
src = In.ar(b.index); | |
comp = Shaper.ar(~compress_buf.bufnum, src); | |
x = SelectX.ar(compAmt, [src, comp]); | |
crush = (x.abs * steps).round * x.sign / steps; | |
exp = Shaper.ar(~expand_buf.bufnum, crush); | |
ReplaceOut.ar(b.index, SelectX.ar(expAmt, [crush, exp])); | |
}.play(s, target:s, addAction:\addToTail); | |
s.sync; | |
~output = { arg amp=0; | |
Out.ar(0, amp.lag(0.1) * In.ar(b.index).dup) | |
}.play(target:~crush, addAction:\addAfter); | |
{ | |
b.scope; | |
w = Window.new("ulawcrush", 600@140); | |
q = w.addFlowLayout(0@0,0@0); | |
EZSlider(w, 600@20, "hz", | |
ControlSpec(20, 7040, \exponential, default: 110, units:\Hz), | |
{|sl| ~sine.set(\hz, sl.value) } | |
); | |
EZSlider(w, 600@20, "steps", | |
ControlSpec(1, 1024, step:1, default:256), | |
{|sl| ~crush.set(\steps, sl.value) } | |
); | |
EZSlider(w, 600@20, "compression", | |
ControlSpec(0, 1, step:0, default:1), | |
{|sl| ~crush.set(\compAmt, sl.value) } | |
); | |
EZSlider(w, 600@20, "expansion", | |
ControlSpec(0, 1, step:0, default:1), | |
{|sl| ~crush.set(\expAmt, sl.value) } | |
); | |
EZSlider(w, 600@20, "sine", | |
ControlSpec(-60, 0, default:-60, units:\dB), | |
{|sl| ~sine.set(\amp, sl.value.dbamp) } | |
); | |
EZSlider(w, 600@20, "input", | |
ControlSpec(-60, 0, default:-60, units:\dB), | |
{|sl| ~input.set(\amp, sl.value.dbamp) } | |
); | |
EZSlider(w, 600@20, "output", | |
ControlSpec(-60, -6, default:-60, units:\dB), | |
{|sl| ~output.set(\amp, sl.value.dbamp) } | |
); | |
w.front; | |
}.defer; | |
}.play; | |
) | |
// try without buffer | |
// | |
// spoiler: doesn't work great. | |
// aside from performance, expect numerical issues | |
/* | |
( | |
Routine { s = Server.default.waitForBoot; | |
// bit crush with u-law | |
SynthDef.new(\compand_crush, { | |
arg io=0, mu=255, steps=256; | |
var x = In.ar(io); | |
// compress | |
x = x.sign * log(1+mu * x.abs) / log(1 + mu); | |
// crush | |
x = (x.abs * steps).round * x.sign / steps; | |
// expand | |
x = x.sign / mu * ((1+mu)**(x.abs) - 1); | |
ReplaceOut.ar(io, x); | |
}).send(s); | |
//... etc | |
}.play; | |
) | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment