├── _assets ├── bitDAC.jpg ├── bitDAC.pdf ├── bitRot.jpg ├── bitRot.pdf ├── dsm1_bitBus.jpg ├── dsm1_bitBus.pdf ├── dsm1_block.jpg ├── dsm1_block.pdf ├── dsm2-drawn.jpg ├── dsm2-drawn.pdf ├── bitDSP_unfolding.jpg ├── bitDSP_unfolding.pdf ├── ShiftRegister-LFSR.jpg └── ShiftRegister-LFSR.pdf ├── test ├── intDivision.dsp ├── test_bitDAC.dsp ├── dsm2_svg.dsp ├── literals.dsp ├── tillRBN.dsp ├── test_bitMask.dsp ├── test_autoparam.dsp ├── test_lfsr.dsp ├── test_bit_delay.dsp └── rbn.dsp ├── .gitignore ├── examples ├── _sc │ ├── DSM2.sc │ ├── DSMAdd.dsp │ ├── boolOsc1.dsp │ ├── boolOsc2.dsp │ ├── DSM2bipolar.dsp │ ├── DSM2unipolar.dsp │ ├── boolOsc0.dsp │ ├── DSMSine.dsp │ ├── DSM2PCM.dsp │ ├── RawLFSR.dsp │ ├── lfsr.dsp │ ├── BoolOscFB.dsp │ ├── BoolOscFB1.dsp │ └── BoolOscFB3.dsp ├── bitDAC.dsp ├── bitstreamAdder.dsp ├── ca.dsp ├── dsm1.dsp ├── dsm2.dsp ├── rbn.dsp ├── lfsr32.dsp ├── bitRot.dsp ├── lfsrNoGUI.dsp └── lfsr.dsp ├── synths ├── _sc │ ├── Bfb.dsp │ ├── Trck.dsp │ ├── Higks.dsp │ ├── DarioGen1.dsp │ ├── DarioGen2.dsp │ ├── DarioGen3.dsp │ ├── DarioGen4.dsp │ └── LowPressure.dsp ├── boolOsc0.dsp ├── LowPressure.dsp ├── Trck.dsp ├── Higks.dsp ├── Bfb.dsp ├── BoolOscFB1.dsp └── BoolOscFB3.dsp ├── LICENSE ├── include └── bitDSP.h ├── lib ├── bandpass.lib ├── bitDSP_conversion.lib ├── bitDSP_bitBus.lib ├── bitDSP_gen.lib ├── bitDSP_int32.lib └── bitDSP.lib ├── works └── BASP.dsp └── README.md /_assets/bitDAC.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rottingsounds/bitDSP-faust/HEAD/_assets/bitDAC.jpg -------------------------------------------------------------------------------- /_assets/bitDAC.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rottingsounds/bitDSP-faust/HEAD/_assets/bitDAC.pdf -------------------------------------------------------------------------------- /_assets/bitRot.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rottingsounds/bitDSP-faust/HEAD/_assets/bitRot.jpg -------------------------------------------------------------------------------- /_assets/bitRot.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rottingsounds/bitDSP-faust/HEAD/_assets/bitRot.pdf -------------------------------------------------------------------------------- /_assets/dsm1_bitBus.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rottingsounds/bitDSP-faust/HEAD/_assets/dsm1_bitBus.jpg -------------------------------------------------------------------------------- /_assets/dsm1_bitBus.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rottingsounds/bitDSP-faust/HEAD/_assets/dsm1_bitBus.pdf -------------------------------------------------------------------------------- /_assets/dsm1_block.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rottingsounds/bitDSP-faust/HEAD/_assets/dsm1_block.jpg -------------------------------------------------------------------------------- /_assets/dsm1_block.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rottingsounds/bitDSP-faust/HEAD/_assets/dsm1_block.pdf -------------------------------------------------------------------------------- /_assets/dsm2-drawn.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rottingsounds/bitDSP-faust/HEAD/_assets/dsm2-drawn.jpg -------------------------------------------------------------------------------- /_assets/dsm2-drawn.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rottingsounds/bitDSP-faust/HEAD/_assets/dsm2-drawn.pdf -------------------------------------------------------------------------------- /_assets/bitDSP_unfolding.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rottingsounds/bitDSP-faust/HEAD/_assets/bitDSP_unfolding.jpg -------------------------------------------------------------------------------- /_assets/bitDSP_unfolding.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rottingsounds/bitDSP-faust/HEAD/_assets/bitDSP_unfolding.pdf -------------------------------------------------------------------------------- /_assets/ShiftRegister-LFSR.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rottingsounds/bitDSP-faust/HEAD/_assets/ShiftRegister-LFSR.jpg -------------------------------------------------------------------------------- /_assets/ShiftRegister-LFSR.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rottingsounds/bitDSP-faust/HEAD/_assets/ShiftRegister-LFSR.pdf -------------------------------------------------------------------------------- /test/intDivision.dsp: -------------------------------------------------------------------------------- 1 | import("stdfaust.lib"); 2 | 3 | a = int(os.osc(440) * 20); 4 | b = 7; 5 | process = int(a/b); 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | myDevelopment 2 | examples/*.app 3 | **/Builds 4 | **/JuceLibraryCode 5 | **/*.app 6 | 7 | **/_sc/*.sc 8 | **/_sc/*.scd 9 | -------------------------------------------------------------------------------- /test/test_bitDAC.dsp: -------------------------------------------------------------------------------- 1 | import("stdfaust.lib"); 2 | b = library("bitDSP.lib"); 3 | 4 | process = b.bitDAC(6, 0, int(no.noise * b.int_max)); 5 | -------------------------------------------------------------------------------- /test/dsm2_svg.dsp: -------------------------------------------------------------------------------- 1 | import("stdfaust.lib"); 2 | integrator = fi.pole(1); 3 | Q(x) = ba.if(x < 0, -1, 1); 4 | process(x) = ((x - _ : integrator) - _ * 2 : integrator : Q) ~ (_ <: _ , _); 5 | -------------------------------------------------------------------------------- /test/literals.dsp: -------------------------------------------------------------------------------- 1 | import("stdfaust.lib"); 2 | b = library("bitDSP.lib"); 3 | 4 | // CXXFLAGS="-I ../lib" faust2csvplot -I ../lib literals.dsp 5 | s_count = (1:+~_) - 1; 6 | 7 | a = (4:b.left_shift(1)) | (6:b.left_shift(1)) | (31:b.left_shift(1)); 8 | process = a : b.print2(0, s_count); 9 | -------------------------------------------------------------------------------- /test/tillRBN.dsp: -------------------------------------------------------------------------------- 1 | import("stdfaust.lib"); 2 | bitConv = library("bitDSP_conversion"); // conversion between formats library 3 | 4 | 5 | 6 | node(function_seed, select_seed, N, K) = si.bus(N) : r_select(select_seed, K) : si.bus(K) : s_node(function_seed) with { 7 | s_node(seed, K) = si.bus(K) : bitConv.bitBus_to_int(K) : sc.hasher(seed + _) > 0.5 : _; 8 | }; 9 | -------------------------------------------------------------------------------- /examples/_sc/DSM2.sc: -------------------------------------------------------------------------------- 1 | DSM2 : UGen 2 | { 3 | *ar { | in1, polarity = \unipolar | 4 | (polarity == \unipolar).if({ 5 | ^DSM2unipolar.ar(in1); 6 | }, { 7 | ^DSM2bipolar.ar(in1); 8 | }) 9 | } 10 | 11 | *kr { | in1, polarity = \unipolar | 12 | (polarity == \unipolar).if({ 13 | ^DSM2unipolar.kr(in1); 14 | }, { 15 | ^DSM2bipolar.kr(in1); 16 | }) 17 | } 18 | } 19 | 20 | -------------------------------------------------------------------------------- /test/test_bitMask.dsp: -------------------------------------------------------------------------------- 1 | import("stdfaust.lib"); 2 | b = library("bitDSP.lib"); 3 | 4 | // compile 5 | // CXXFLAGS="-I ../lib" faust2csvplot -I ../lib bitMask.dsp 6 | // ./bitMask -n 10 7 | 8 | s_count = (1:+~_) - 1; 9 | 10 | // a = (4:b.left_shift(1)) | (6:b.left_shift(1)) | (31:b.left_shift(1)); 11 | a = b.bit_mask((s_count % 32, 6, 31)); 12 | 13 | process = a : b.print2(0, s_count); 14 | -------------------------------------------------------------------------------- /test/test_autoparam.dsp: -------------------------------------------------------------------------------- 1 | import("stdfaust.lib"); 2 | inspect(i) = bit.inspect(i, -1, 1); 3 | bit = library("bitDSP.lib"); 4 | gen = library("bitDSP_gen.lib"); 5 | fb1 = hslider("fb1", 0.1, -1, 1, .000001); 6 | fb2 = hslider("fb2", 0.1, -1, 1, .000001); 7 | 8 | process = gen.gen3 ~ (ro.cross(2) : par(i, 2, bit.autoparam + .54233) : par(i, 2, inspect(i))) : par(i, 2, fi.highpass(1, 20)); 9 | 10 | //process = gen.gen3(fb1, fb2) <: par(i, 2, fi.highpass(1, 20)) , (par(i, 2, bit.autoparam) : par(i, 2, inspect(i))); 11 | 12 | -------------------------------------------------------------------------------- /synths/_sc/Bfb.dsp: -------------------------------------------------------------------------------- 1 | declare name "Bfb"; 2 | declare author "Till Bovermann"; 3 | declare reference "http://rottingsounds.org"; 4 | 5 | import("stdfaust.lib"); 6 | // bit = library("bitDSP.lib"); 7 | bit_gen = library("bitDSP_gen.lib"); 8 | 9 | // SuperCollider 10 | // export SUPERCOLLIDER_HEADERS=/localvol/sound/src/supercollider/include/ 11 | // faust2supercollider -I ../../lib -noprefix Bfb.dsp 12 | 13 | c1 = hslider("c1",0,0,1,0.001); 14 | c2 = hslider("c2",0.5,0,1,0.001); 15 | 16 | // Final output 17 | process = bit_gen.bfb(c1, c2) : si.bus(2); 18 | -------------------------------------------------------------------------------- /synths/_sc/Trck.dsp: -------------------------------------------------------------------------------- 1 | declare name "Trck"; 2 | declare author "Till Bovermann"; 3 | declare reference "http://rottingsounds.org"; 4 | 5 | import("stdfaust.lib"); 6 | // bit = library("bitDSP.lib"); 7 | bit_gen = library("bitDSP_gen.lib"); 8 | 9 | // SuperCollider 10 | // export SUPERCOLLIDER_HEADERS=/localvol/sound/src/supercollider/include/ 11 | // faust2supercollider -I ../../lib -noprefix Trck.dsp 12 | 13 | c1 = hslider("c1",0,0,1,0.001); 14 | c2 = hslider("c2",0.5,0,1,0.001); 15 | 16 | // Final output 17 | process = bit_gen.trck(c1, c2) : si.bus(2); 18 | -------------------------------------------------------------------------------- /synths/_sc/Higks.dsp: -------------------------------------------------------------------------------- 1 | declare name "Higks"; 2 | declare author "Till Bovermann"; 3 | declare reference "http://rottingsounds.org"; 4 | 5 | import("stdfaust.lib"); 6 | // bit = library("bitDSP.lib"); 7 | bit_gen = library("bitDSP_gen.lib"); 8 | 9 | // SuperCollider 10 | // export SUPERCOLLIDER_HEADERS=/localvol/sound/src/supercollider/include/ 11 | // faust2supercollider -I ../../lib -noprefix Higks.dsp 12 | 13 | c1 = hslider("c1",0,0,1,0.001); 14 | c2 = hslider("c2",0.5,0,1,0.001); 15 | 16 | // Final output 17 | process = bit_gen.higks(c1, c2) : si.bus(2); 18 | -------------------------------------------------------------------------------- /synths/_sc/DarioGen1.dsp: -------------------------------------------------------------------------------- 1 | declare name "DarioGen1"; 2 | declare author "Till Bovermann"; 3 | declare reference "http://rottingsounds.org"; 4 | 5 | import("stdfaust.lib"); 6 | // bit = library("bitDSP.lib"); 7 | bit_gen = library("bitDSP_gen.lib"); 8 | 9 | // SuperCollider 10 | // export SUPERCOLLIDER_HEADERS=/localvol/sound/src/supercollider/include/ 11 | // faust2supercollider -I ../../lib -noprefix DarioGen1.dsp 12 | 13 | c1 = hslider("c1",0,0,1,0.001); 14 | c2 = hslider("c2",0.5,0,1,0.001); 15 | 16 | // Final output 17 | process = bit_gen.gen1(c1, c2) : si.bus(2); 18 | -------------------------------------------------------------------------------- /synths/_sc/DarioGen2.dsp: -------------------------------------------------------------------------------- 1 | declare name "DarioGen2"; 2 | declare author "Till Bovermann"; 3 | declare reference "http://rottingsounds.org"; 4 | 5 | import("stdfaust.lib"); 6 | // bit = library("bitDSP.lib"); 7 | bit_gen = library("bitDSP_gen.lib"); 8 | 9 | // SuperCollider 10 | // export SUPERCOLLIDER_HEADERS=/localvol/sound/src/supercollider/include/ 11 | // faust2supercollider -I ../../lib -noprefix DarioGen2.dsp 12 | 13 | c1 = hslider("c1",0,0,1,0.001); 14 | c2 = hslider("c2",0.5,0,1,0.001); 15 | 16 | // Final output 17 | process = bit_gen.gen2(c1, c2) : si.bus(2); 18 | -------------------------------------------------------------------------------- /synths/_sc/DarioGen3.dsp: -------------------------------------------------------------------------------- 1 | declare name "DarioGen3"; 2 | declare author "Till Bovermann"; 3 | declare reference "http://rottingsounds.org"; 4 | 5 | import("stdfaust.lib"); 6 | // bit = library("bitDSP.lib"); 7 | bit_gen = library("bitDSP_gen.lib"); 8 | 9 | // SuperCollider 10 | // export SUPERCOLLIDER_HEADERS=/localvol/sound/src/supercollider/include/ 11 | // faust2supercollider -I ../../lib -noprefix DarioGen3.dsp 12 | 13 | c1 = hslider("c1",0,0,1,0.001); 14 | c2 = hslider("c2",0.5,0,1,0.001); 15 | 16 | // Final output 17 | process = bit_gen.gen1(c1, c2) : si.bus(2); 18 | -------------------------------------------------------------------------------- /synths/_sc/DarioGen4.dsp: -------------------------------------------------------------------------------- 1 | declare name "DarioGen4"; 2 | declare author "Till Bovermann"; 3 | declare reference "http://rottingsounds.org"; 4 | 5 | import("stdfaust.lib"); 6 | // bit = library("bitDSP.lib"); 7 | bit_gen = library("bitDSP_gen.lib"); 8 | 9 | // SuperCollider 10 | // export SUPERCOLLIDER_HEADERS=/localvol/sound/src/supercollider/include/ 11 | // faust2supercollider -I ../../lib -noprefix DarioGen4.dsp 12 | 13 | c1 = hslider("c1",0,0,1,0.001); 14 | c2 = hslider("c2",0.5,0,1,0.001); 15 | 16 | // Final output 17 | process = bit_gen.gen4(c1, c2) : si.bus(2); 18 | -------------------------------------------------------------------------------- /synths/_sc/LowPressure.dsp: -------------------------------------------------------------------------------- 1 | declare name "LowPressure"; 2 | declare author "Till Bovermann"; 3 | declare reference "http://rottingsounds.org"; 4 | 5 | import("stdfaust.lib"); 6 | // bit = library("bitDSP.lib"); 7 | bit_gen = library("bitDSP_gen.lib"); 8 | 9 | // SuperCollider 10 | // export SUPERCOLLIDER_HEADERS=/localvol/sound/src/supercollider/include/ 11 | // faust2supercollider -I ../../lib -noprefix LowPressure.dsp 12 | 13 | c1 = hslider("c1",0,0,1,0.001); 14 | c2 = hslider("c2",0.5,0,1,0.001); 15 | 16 | // Final output 17 | process = bit_gen.lowPressure(c1, c2) : si.bus(2); 18 | -------------------------------------------------------------------------------- /test/test_lfsr.dsp: -------------------------------------------------------------------------------- 1 | declare name "lfsr printVals"; 2 | declare author "Till Bovermann"; 3 | declare reference "http://rottingsounds.org"; 4 | 5 | import("stdfaust.lib"); 6 | bit32 = library("bitDSP_int32.lib"); 7 | 8 | // plot 9 | // CXXFLAGS="-I ../include" faust2csvplot -I ../lib lfsr.dsp 10 | // ./lfsr -n 10 11 | 12 | // compile 13 | // CXXFLAGS="-I ../../../include" faust2caqt -I ../lib lfsr.dsp 14 | // ./lfsr 15 | 16 | 17 | s_count = (1:+~_) - 1; 18 | 19 | // a = (4:b.left_shift(1)) | (6:bit32.left_shift(1)) | (31:bit32.left_shift(1)); 20 | a = 1: bit32.lfsr32(b.bit_mask((3, 6, 31))); 21 | 22 | process = a : bit32.print2(0, s_count); 23 | -------------------------------------------------------------------------------- /test/test_bit_delay.dsp: -------------------------------------------------------------------------------- 1 | import("stdfaust.lib"); 2 | 3 | b = library("bitDSP.lib"); 4 | 5 | // bit_delay(0, x) = x; 6 | // bit_delay(32, x) = x'; 7 | // bit_delay(delta, x) = ((x >> delta) | (x' << (32-delta))); 8 | 9 | line = 1:+~_; 10 | 11 | input = select2(1', -1216614433, 1216614432); 12 | 13 | s_count = (1:+~_) - 1; 14 | 15 | // parallel execution of the 32 cases for the bit_delay, 16 | // I'd like to feed all of them the two values I defined in `input`, 17 | // where the first value (-1216614433) is x' and the second value (1216614432) is x 18 | 19 | process = input <: par(i,32,b.delay32(i) : b.print2(s_count, i)); 20 | 21 | // process = input <: par(i,32,b.delay32(i)); -------------------------------------------------------------------------------- /synths/boolOsc0.dsp: -------------------------------------------------------------------------------- 1 | declare name "boolOsc0"; 2 | declare description "bool_osc_0 - example"; 3 | declare author "Till Bovermann"; 4 | declare reference "http://rottingsounds.org"; 5 | 6 | import("stdfaust.lib"); 7 | bit = library("bitDSP.lib"); 8 | 9 | // plot 10 | // CXXFLAGS="-I ../include" faust2csvplot -I ../lib boolOsc0.dsp 11 | // ./boolOsc0 -n 10 12 | 13 | // compile 14 | // CXXFLAGS="-I ../../../include" faust2caqt -I ../lib boolOsc0.dsp 15 | // ./boolOsc0 16 | 17 | dt1 = int(hslider("dt1",0,0,1,0) * ma.SR); 18 | dt2 = int(hslider("dt2",0,0,1,0) * ma.SR); 19 | dt3 = int(hslider("dt3",0,0,1,0) * ma.SR); 20 | dt4 = int(hslider("dt4",0,0,1,0) * ma.SR); 21 | 22 | 23 | // stereo out 24 | process = bit.bool_osc0(dt1, dt2, dt3, dt4) <: _, _; -------------------------------------------------------------------------------- /examples/_sc/DSMAdd.dsp: -------------------------------------------------------------------------------- 1 | declare name "DSMAdd"; 2 | declare author "Till Bovermann, Dario Sanfilippo"; 3 | declare reference "http://rottingsounds.org"; 4 | 5 | import("stdfaust.lib"); 6 | bit = library("bitDSP.lib"); 7 | 8 | // plot 9 | // CXXFLAGS="-I ../include" faust2csvplot -double -I ../lib DSMAdd.dsp 10 | // ./DSM2bipolar -n 10 11 | 12 | // compile 13 | // CXXFLAGS="-I ../../../include" faust2caqt -double -I ../lib DSMAdd.dsp 14 | // ./DSM2bipolar 15 | 16 | // SuperCollider 17 | // export SUPERCOLLIDER_HEADERS=/localvol/sound/src/supercollider/include/ 18 | // faust2supercollider -I ../faust/bitDSP-faust/lib -noprefix DSMAdd.dsp 19 | 20 | // Final output 21 | // Bipolar multi-bit signal to bipolar one-bit signal 22 | process = bit.bitstream_adder; 23 | -------------------------------------------------------------------------------- /examples/_sc/boolOsc1.dsp: -------------------------------------------------------------------------------- 1 | declare name "boolOsc1"; 2 | declare description "bool_osc_0 - example"; 3 | declare author "Till Bovermann"; 4 | declare reference "http://rottingsounds.org"; 5 | 6 | import("stdfaust.lib"); 7 | bit = library("bitDSP.lib"); 8 | 9 | 10 | // SuperCollider 11 | // CXXFLAGS="-I ../../../../include" faust2supercollider -I ../../lib -noprefix boolOsc1.dsp 12 | 13 | // plot 14 | // CXXFLAGS="-I ../include" faust2csvplot -I ../lib boolOsc1.dsp 15 | // ./boolOsc1 -n 10 16 | 17 | // compile 18 | // CXXFLAGS="-I ../../../include" faust2caqt -I ../lib boolOsc1.dsp 19 | // ./boolOsc1 20 | 21 | 22 | dt1 = int(hslider("dt1",0,0,1,0) * ma.SR); 23 | dt2 = int(hslider("dt2",0,0,1,0) * ma.SR); 24 | 25 | // mono out 26 | process = bit.bool_osc1(dt1, dt2); -------------------------------------------------------------------------------- /examples/_sc/boolOsc2.dsp: -------------------------------------------------------------------------------- 1 | declare name "boolOsc2"; 2 | declare description "bool_osc_0 - example"; 3 | declare author "Till Bovermann"; 4 | declare reference "http://rottingsounds.org"; 5 | 6 | import("stdfaust.lib"); 7 | bit = library("bitDSP.lib"); 8 | 9 | 10 | // SuperCollider 11 | // CXXFLAGS="-I ../../../../include" faust2supercollider -I ../../lib -noprefix boolOsc2.dsp 12 | 13 | // plot 14 | // CXXFLAGS="-I ../include" faust2csvplot -I ../lib boolOsc2.dsp 15 | // ./boolOsc2 -n 10 16 | 17 | // compile 18 | // CXXFLAGS="-I ../../../include" faust2caqt -I ../lib boolOsc2.dsp 19 | // ./boolOsc2 20 | 21 | 22 | dt1 = int(hslider("dt1",0,0,1,0) * ma.SR); 23 | dt2 = int(hslider("dt2",0,0,1,0) * ma.SR); 24 | 25 | // mono out 26 | process = bit.bool_osc2(dt1, dt2); -------------------------------------------------------------------------------- /examples/_sc/DSM2bipolar.dsp: -------------------------------------------------------------------------------- 1 | declare name "DSM2bipolar"; 2 | declare author "Till Bovermann, Dario Sanfilippo"; 3 | declare reference "http://rottingsounds.org"; 4 | 5 | import("stdfaust.lib"); 6 | bit = library("bitDSP.lib"); 7 | 8 | // plot 9 | // CXXFLAGS="-I ../include" faust2csvplot -double -I ../lib DSM2bipolar.dsp 10 | // ./DSM2bipolar -n 10 11 | 12 | // compile 13 | // CXXFLAGS="-I ../../../include" faust2caqt -double -I ../lib DSM2bipolar.dsp 14 | // ./DSM2bipolar 15 | 16 | // SuperCollider 17 | // export SUPERCOLLIDER_HEADERS=/localvol/sound/src/supercollider/include/ 18 | // faust2supercollider -I ../faust/bitDSP-faust/lib -noprefix DSM2bipolar.dsp 19 | 20 | // Final output 21 | // Bipolar multi-bit signal to bipolar one-bit signal 22 | process = bit.dsm2; 23 | -------------------------------------------------------------------------------- /examples/_sc/DSM2unipolar.dsp: -------------------------------------------------------------------------------- 1 | declare name "DSM2unipolar"; 2 | declare author "Till Bovermann, Dario Sanfilippo"; 3 | declare reference "http://rottingsounds.org"; 4 | 5 | import("stdfaust.lib"); 6 | bit = library("bitDSP.lib"); 7 | 8 | // plot 9 | // CXXFLAGS="-I ../include" faust2csvplot -double -I ../lib DSM2unipolar.dsp 10 | // ./DSM2unipolar -n 10 11 | 12 | // compile 13 | // CXXFLAGS="-I ../../../include" faust2caqt -double -I ../lib DSM2unipolar.dsp 14 | // ./DSM2unipolar 15 | 16 | // SuperCollider 17 | // export SUPERCOLLIDER_HEADERS=/localvol/sound/src/supercollider/include/ 18 | // faust2supercollider -I ../faust/bitDSP-faust/lib -noprefix DSM2unipolar.dsp 19 | 20 | // Final output 21 | // Bipolar multi-bit signal to bipolar one-bit signal 22 | process = bit.dsm2 > 0; 23 | -------------------------------------------------------------------------------- /examples/bitDAC.dsp: -------------------------------------------------------------------------------- 1 | declare name "bitDAC"; 2 | declare description "bitDAC - example"; 3 | declare author "Till Bovermann"; 4 | declare reference "http://rottingsounds.org"; 5 | 6 | import("stdfaust.lib"); 7 | bit32 = library("bitDSP_int32.lib"); 8 | 9 | // plot 10 | // CXXFLAGS="-I ../include" faust2csvplot -I ../lib bitDAC.dsp 11 | // ./bitDAC -n 10 12 | 13 | // compile 14 | // CXXFLAGS="-I ../../../include" faust2caqt -I ../lib bitDAC.dsp 15 | // ./bitDAC 16 | 17 | dac_bits = int(hslider("dac bits",1,1,32,1)); 18 | dac_offset = min(int(hslider("dac offset",0,0,31,1)), 32-dac_bits); 19 | 20 | // counting samples from start of execution, starting at 0 21 | sample_count = int((1:+~_)) - 1; 22 | 23 | 24 | 25 | // select bits of the samplecount and interpret that chunk as a PCM value 26 | 27 | process = bit32.bitDAC(dac_offset, dac_bits, sample_count) <: _,_; -------------------------------------------------------------------------------- /examples/_sc/boolOsc0.dsp: -------------------------------------------------------------------------------- 1 | declare name "boolOsc0"; 2 | declare description "bool_osc_0 - example"; 3 | declare author "Till Bovermann"; 4 | declare reference "http://rottingsounds.org"; 5 | 6 | import("stdfaust.lib"); 7 | bit = library("bitDSP.lib"); 8 | 9 | 10 | // SuperCollider 11 | // CXXFLAGS="-I ../../../../include" faust2supercollider -I ../../lib -noprefix boolOsc0.dsp 12 | 13 | // plot 14 | // CXXFLAGS="-I ../include" faust2csvplot -I ../lib boolOsc0.dsp 15 | // ./boolOsc0 -n 10 16 | 17 | // compile 18 | // CXXFLAGS="-I ../../../include" faust2caqt -I ../lib boolOsc0.dsp 19 | // ./boolOsc0 20 | 21 | 22 | dt1 = int(hslider("dt1",0,0,1,0) * ma.SR); 23 | dt2 = int(hslider("dt2",0,0,1,0) * ma.SR); 24 | dt3 = int(hslider("dt3",0,0,1,0) * ma.SR); 25 | dt4 = int(hslider("dt4",0,0,1,0) * ma.SR); 26 | 27 | // mono out 28 | process = bit.bool_osc0(dt1, dt2, dt3, dt4); -------------------------------------------------------------------------------- /examples/_sc/DSMSine.dsp: -------------------------------------------------------------------------------- 1 | declare name "DSMSine"; 2 | declare author "Till Bovermann, Dario Sanfilippo"; 3 | declare reference "http://rottingsounds.org"; 4 | 5 | import("stdfaust.lib"); 6 | bit = library("bitDSP.lib"); 7 | 8 | // plot 9 | // CXXFLAGS="-I ../include" faust2csvplot -double -I ../lib dsm2-example.dsp 10 | // ./DSMSine -n 10 11 | 12 | // compile 13 | // CXXFLAGS="-I ../../../include" faust2caqt -double -I ../lib dsm2-example.dsp 14 | // open ./DSMSine 15 | 16 | // SuperCollider 17 | // export SUPERCOLLIDER_HEADERS=/localvol/sound/src/supercollider/include/ 18 | // faust2supercollider -I ../faust/bitDSP-faust/lib -noprefix DSMSine.dsp 19 | 20 | freq = hslider("freq",100,0,20000,0); 21 | 22 | // High-precision sinewave 23 | sine(f) = sin(os.phasor(2 * ma.PI, f)); 24 | 25 | // Bipolar multi-bit signal to bipolar one-bit signal 26 | // Standard test with a 1 kHz tone 27 | onebitstream = bit.dsm2(sine(freq)); 28 | 29 | // Final output 30 | process = onebitstream; 31 | -------------------------------------------------------------------------------- /examples/bitstreamAdder.dsp: -------------------------------------------------------------------------------- 1 | // This is a simple example that tests an adder for 1-bit streams. 2 | // In this example, in particular, we will add together a stream 3 | // of 1s and a stream of 0s. Summing two opposite values results 4 | // in a zero-ed output, which consists of alternating 0s and 1s 5 | // in the delta-sigma-modulated domain. 6 | 7 | declare name "Bitstream adder"; 8 | declare author "Dario Sanfilippo"; 9 | declare reference "O'leary, P., & Maloberti, F. (1990). Bit stream adder 10 | for oversampling coded data. Electronics Letters, 26(20), 1708-1709."; 11 | 12 | import("stdfaust.lib"); 13 | bit = library("bitDSP.lib"); 14 | 15 | // plot 16 | // CXXFLAGS="-I ../include" faust2csvplot -double -I ../lib 17 | // bitstream_adder-example.dsp 18 | // ./bitstream_adder-example -n 50 19 | 20 | // compile 21 | // CXXFLAGS="-I ../../../include" faust2caqt -double -I ../lib 22 | // bitstream_adder-example.dsp 23 | // ./bitstream_adder-example 24 | 25 | process = bit.bitstream_adder(0, 1); 26 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 rotting-sounds 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /examples/ca.dsp: -------------------------------------------------------------------------------- 1 | // This is a simple example showing pattern-formation through 2 | // elementary cellular automata. The cellular automata function 3 | // is called with four integer arguments: size of the circular lattice; 4 | // the rule that determines the next state of each cell; the initial 5 | // state of the cells; the iteration rate. 6 | // 7 | // The size of the lattice also determines the number of outputs of the 8 | // function. The patterns can be displayed easily compiling the 9 | // faust2csvplot program as indicated below. 10 | 11 | declare name "ca"; 12 | declare description "Elementary cellular automata – size-16 lattice example; rule 110"; 13 | declare author "Dario Sanfilippo"; 14 | declare reference "Stephen Wolfram – A New Kind of Science (2002)"; 15 | 16 | import("stdfaust.lib"); 17 | bitBus = library("bitDSP_bitBus.lib"); 18 | 19 | // plot 20 | // CXXFLAGS="-I ../include" faust2csvplot -double -I ../lib ca-example.dsp 21 | // ./ca-example -n 50 22 | 23 | // compile 24 | // CXXFLAGS="-I ../../../include" faust2caqt -double -I ../lib ca-example.dsp 25 | // ./ca-example 26 | 27 | process = bitBus.eca(16, 110, 24, ma.SR); 28 | 29 | 30 | -------------------------------------------------------------------------------- /examples/_sc/DSM2PCM.dsp: -------------------------------------------------------------------------------- 1 | declare name "DSM2PCM"; 2 | declare author "Till Bovermann, Dario Sanfilippo"; 3 | declare reference "http://rottingsounds.org"; 4 | 5 | import("stdfaust.lib"); 6 | bit = library("bitDSP.lib"); 7 | 8 | // plot 9 | // CXXFLAGS="-I ../include" faust2csvplot -double -I ../lib DSM2PCM.dsp 10 | // ./DSM2PCM -n 10 11 | 12 | // compile 13 | // CXXFLAGS="-I ../../../include" faust2caqt -double -I ../lib DSM2PCM.dsp 14 | // ./DSM2PCM 15 | 16 | // SuperCollider 17 | // export SUPERCOLLIDER_HEADERS=/localvol/sound/src/supercollider/include/ 18 | // faust2supercollider -double -I ../faust/bitDSP-faust/lib -noprefix DSM2PCM.dsp 19 | 20 | // downsample_factor = hslider("downsample",2,2,64,2); 21 | freq = hslider("freq", 100, 100, 192000, 0); 22 | 23 | // Bipolar one-bit signal to bipolar multi-bit signal 24 | // The process of low-passing corresponds to averaging 25 | // The low-pass cut-off sets the target bandwidth 26 | // The low-pass resolution of the coefficients sets the bitdepth 27 | // The low-pass order determines the accuracy in the noise removal 28 | // process = fi.lowpass(8, ma.SR / downsample_factor); 29 | process = fi.lowpass(8, freq); 30 | -------------------------------------------------------------------------------- /examples/dsm1.dsp: -------------------------------------------------------------------------------- 1 | declare name "dsm1"; 2 | declare description "First-order delta-sigma modulator - example"; 3 | declare author "Till Bovermann"; 4 | declare reference "http://rottingsounds.org"; 5 | 6 | import("stdfaust.lib"); 7 | bit = library("bitDSP.lib"); 8 | 9 | // plot 10 | // CXXFLAGS="-I ../include" faust2csvplot -double -I ../lib dsm1-example.dsp 11 | // ./dsm1-example -n 10 12 | 13 | // compile 14 | // CXXFLAGS="-I ../../../include" faust2caqt -double -I ../lib dsm1-example.dsp 15 | // ./dsm1-example 16 | 17 | // High-precision sinewave 18 | sine(f) = sin(os.phasor(2 * ma.PI, f)); 19 | 20 | // Bipolar multi-bit signal to bipolar one-bit signal 21 | // Standard test with a 1 kHz tone 22 | onebitstream = bit.dsm1(sine(1000)); 23 | 24 | // Bipolar one-bit signal to bipolar multi-bit signal 25 | // The process of low-passing corresponds to averaging 26 | // The low-pass cut-off sets the target bandwidth 27 | // The low-pass resolution of the coefficients sets the bitdepth 28 | // The low-pass order determines the accuracy in the noise removal 29 | multibitstream = fi.lowpass(4, 1000, onebitstream); 30 | 31 | // Final output 32 | process = multibitstream; 33 | -------------------------------------------------------------------------------- /synths/LowPressure.dsp: -------------------------------------------------------------------------------- 1 | declare name "LowPressure"; 2 | declare author "Till Bovermann"; 3 | declare reference "http://rottingsounds.org"; 4 | import("stdfaust.lib"); 5 | bit_gen = library("bitDSP_gen.lib"); 6 | // plot 7 | // CXXFLAGS="-I ../include" faust2csvplot -I ../lib LowPressure.dsp 8 | // ./boolOsc0 -n 10 9 | // compile 10 | // CXXFLAGS="-I ../../../include" faust2caqt -I ../lib -double LowPressure.dsp 11 | // ./LowPressure 12 | 13 | 14 | c1 = hslider("c1",0,0,1,0.001); 15 | c2 = hslider("c2",0.5,0,1,0.001); 16 | rot = hslider("rot",0.5,0, ma.PI, 0.001) : si.smoo; 17 | lFreq = hslider("lFreq [scale:log]",100,25, 10000, 1) : si.smoo; 18 | hFreq = hslider("hFreq [scale:log]",100,25, 10000, 1) : si.smoo; 19 | vol = hslider("vol", 0, 0, 1, 0.0001) : si.smoo; 20 | 21 | rotate2(r, x, y) = xout, yout with { 22 | xout = cos(r) * x + sin(r) * y; 23 | yout = cos(r) * y - sin(r) * x; 24 | }; 25 | 26 | 27 | // process = bit_gen.lowPressure(c1, c2) : par(i, 2, (_ * vol)); 28 | 29 | 30 | 31 | process = bit_gen.lowPressure(c1, c2) 32 | : par( i, 2, _ * vol) 33 | : par( i, 2, _ * 2 -1 <: fi.svf.lp(lFreq, 20) - fi.svf.lp(hFreq, 50)) 34 | : rotate2(rot); 35 | -------------------------------------------------------------------------------- /examples/dsm2.dsp: -------------------------------------------------------------------------------- 1 | declare name "DSM2"; 2 | declare description "Second-order delta-sigma modulator example"; 3 | Second-order delta-sigma modulator - example 4 | declare author "Dario Sanfilippo"; 5 | declare reference "http://rottingsounds.org"; 6 | 7 | import("stdfaust.lib"); 8 | bit = library("bitDSP.lib"); 9 | 10 | // plot 11 | // CXXFLAGS="-I ../include" faust2csvplot -double -I ../lib dsm2.dsp 12 | // ./dsm2 -n 10 13 | 14 | // compile 15 | // CXXFLAGS="-I ../../../include" faust2caqt -double -I ../lib dsm2.dsp 16 | // ./dsm2 17 | 18 | // High-precision sinewave 19 | sine(f) = sin(os.phasor(2 * ma.PI, f)); 20 | 21 | // Bipolar multi-bit signal to bipolar one-bit signal 22 | // Standard test with a 1 kHz tone 23 | onebitstream = bit.dsm2(sine(1000)); 24 | 25 | // Bipolar one-bit signal to bipolar multi-bit signal 26 | // The process of low-passing corresponds to averaging 27 | // The low-pass cut-off sets the target bandwidth 28 | // The low-pass resolution of the coefficients sets the bitdepth 29 | // The low-pass order determines the accuracy in the noise removal 30 | multibitstream = fi.lowpass(4, 1000, onebitstream); 31 | 32 | // Final output 33 | process = multibitstream; 34 | -------------------------------------------------------------------------------- /synths/Trck.dsp: -------------------------------------------------------------------------------- 1 | declare name "Trck"; 2 | declare author "Till Bovermann"; 3 | declare reference "http://rottingsounds.org"; 4 | import("stdfaust.lib"); 5 | bit = library("bitDSP.lib"); 6 | bit_gen = library("bitDSP_gen.lib"); 7 | 8 | // plot 9 | // CXXFLAGS="-I ../include" faust2csvplot -I ../lib Trck.dsp 10 | // ./boolOsc0 -n 10 11 | // compile 12 | // CXXFLAGS="-I ../../../include" faust2caqt -I ../lib Trck.dsp 13 | // ./Trck 14 | 15 | import("stdfaust.lib"); 16 | // bit = library("bitDSP.lib"); 17 | 18 | c1 = hslider("c1",0,0,1,0.001); 19 | c2 = hslider("c2",0.5,0,1,0.001); 20 | rot = hslider("rot",0.5,0, ma.PI, 0.001) : si.smoo; 21 | lFreq = hslider("lFreq [scale:log]",100,25, 10000, 1) : si.smoo; 22 | hFreq = hslider("hFreq [scale:log]",100,25, 10000, 1) : si.smoo; 23 | vol = hslider("vol", 0, 0, 1, 0.0001) : si.smoo; 24 | 25 | rotate2(r, x, y) = xout, yout with { 26 | xout = cos(r) * x + sin(r) * y; 27 | yout = cos(r) * y - sin(r) * x; 28 | }; 29 | 30 | 31 | 32 | process = bit_gen.trck(c1, c2) 33 | : par( i, 2, _ * vol) 34 | : par( i, 2, _ * 2 -1 <: fi.svf.lp(lFreq, 20) - fi.svf.lp(hFreq, 50)) 35 | : rotate2(rot); 36 | 37 | 38 | 39 | ////////////////// 40 | -------------------------------------------------------------------------------- /synths/Higks.dsp: -------------------------------------------------------------------------------- 1 | declare name "Higks"; 2 | declare author "Till Bovermann"; 3 | declare reference "http://rottingsounds.org"; 4 | 5 | import("stdfaust.lib"); 6 | bit_gen = library("bitDSP_gen.lib"); 7 | 8 | // SuperCollider 9 | // CXXFLAGS="-I ../../../../include" faust2supercollider -I ../../lib -noprefix Higks.dsp 10 | 11 | // plot 12 | // CXXFLAGS="-I ../include" faust2csvplot -I ../lib Higks.dsp 13 | // ./Higks -n 10 14 | 15 | // compile 16 | // CXXFLAGS="-I ../../../include" faust2caqt -I ../lib -double Higks.dsp 17 | // ./Higks 18 | 19 | 20 | 21 | c1 = hslider("c1",0,0,1,0.001); 22 | c2 = hslider("c2",0.5,0,1,0.001); 23 | rot = hslider("rot",0.5,0, ma.PI, 0.001) : si.smoo; 24 | lFreq = hslider("lFreq [scale:log]",100,25, 10000, 1) : si.smoo; 25 | hFreq = hslider("hFreq [scale:log]",100,25, 10000, 1) : si.smoo; 26 | vol = hslider("vol", 0, 0, 1, 0.0001) : si.smoo; 27 | 28 | rotate2(r, x, y) = xout, yout with { 29 | xout = cos(r) * x + sin(r) * y; 30 | yout = cos(r) * y - sin(r) * x; 31 | }; 32 | 33 | 34 | // process = bit_gen.higks(c1, c2) : par(i, 2, (_ * vol)); 35 | 36 | 37 | 38 | process = bit_gen.higks(c1, c2) 39 | : par( i, 2, _ * vol) 40 | : par( i, 2, _ * 2 -1 <: fi.svf.lp(lFreq, 20) - fi.svf.lp(hFreq, 50)) 41 | : rotate2(rot); 42 | -------------------------------------------------------------------------------- /synths/Bfb.dsp: -------------------------------------------------------------------------------- 1 | declare name "Bfb"; 2 | declare description "bool_osc FB alternative 1"; 3 | declare author "Till Bovermann"; 4 | declare reference "http://rottingsounds.org"; 5 | 6 | import("stdfaust.lib"); 7 | bit_gen = library("bitDSP_gen.lib"); 8 | 9 | // bit = library("bitDSP.lib"); 10 | // SuperCollider 11 | // CXXFLAGS="-I ../../../../include" faust2supercollider -I ../../lib -noprefix Bfb.dsp 12 | // plot 13 | // CXXFLAGS="-I ../include" faust2csvplot -I ../lib Bfb.dsp 14 | // ./boolOsc_fb -n 10 15 | // compile 16 | // CXXFLAGS="-I ../../../include" faust2caqt -I ../lib -double Bfb.dsp 17 | // ./Bfb 18 | 19 | 20 | 21 | 22 | c1 = hslider("c1",0,0,1,0.001); 23 | c2 = hslider("c2",0.5,0,1,0.001); 24 | rot = hslider("rot",0.5,0, ma.PI, 0.001) : si.smoo; 25 | lFreq = hslider("lFreq [scale:log]",100,25, 10000, 1) : si.smoo; 26 | hFreq = hslider("hFreq [scale:log]",100,25, 10000, 1) : si.smoo; 27 | vol = hslider("vol", 0, 0, 1, 0.0001) : si.smoo; 28 | 29 | rotate2(r, x, y) = xout, yout with { 30 | xout = cos(r) * x + sin(r) * y; 31 | yout = cos(r) * y - sin(r) * x; 32 | }; 33 | 34 | 35 | // process = bit_gen.bfb(c1, c2) : par(i, 2, (_ * vol)); 36 | 37 | process = bit_gen.bfb(c1, c2) 38 | : par( i, 2, _ * vol) 39 | : par( i, 2, _ * 2 -1 <: fi.svf.lp(lFreq, 20) - fi.svf.lp(hFreq, 50)) 40 | : rotate2(rot); -------------------------------------------------------------------------------- /examples/rbn.dsp: -------------------------------------------------------------------------------- 1 | // This is a simple example showing the possibilities offered by 2 | // recursivity combined with nonlinear properties of Boolean operators. 3 | // The network in this example is a fourth-order one, hence with four nodes, 4 | // combining identity and circular topologies. The system parameters are 5 | // the delays between the connections, which determine different chaotic 6 | // behaviours ranging from limit cycles to strange attractors and 7 | // unpredictability. 8 | 9 | declare name "RBN"; 10 | declare description "Recursive Boolean network"; 11 | declare author "Dario Sanfilippo"; 12 | declare reference "Stuart A Kauffman, “Metabolic stability and epigenesis 13 | in randomly constructed genetic nets,” Journal of theoretical 14 | biology, vol. 22, no. 3, pp. 437–467, 1969."; 15 | 16 | import("stdfaust.lib"); 17 | bit = library("bitDSP.lib"); 18 | 19 | // plot 20 | // CXXFLAGS="-I ../include" faust2csvplot -double -I ../lib rbn-example.dsp 21 | // ./rbn-example -n 50 22 | 23 | // compile 24 | // CXXFLAGS="-I ../../../include" faust2caqt -double -I ../lib rbn-example.dsp 25 | // ./rbn-example 26 | 27 | d1 = hslider("del1", 0, 0, 9600, 1); 28 | d2 = hslider("del2", 0, 0, 9600, 1); 29 | d3 = hslider("del3", 0, 0, 9600, 1); 30 | d4 = hslider("del4", 0, 0, 9600, 1); 31 | process = bit.bool_osc0(d1, d2, d3, d4); 32 | -------------------------------------------------------------------------------- /examples/lfsr32.dsp: -------------------------------------------------------------------------------- 1 | declare name "LFSR32"; 2 | declare author "Till Bovermann"; 3 | declare description "linear feedback shift register (32bit) example"; 4 | declare reference "http://rottingsounds.org"; 5 | 6 | // see https://en.wikipedia.org/wiki/Linear-feedback_shift_register 7 | 8 | import("stdfaust.lib"); 9 | bit32 = library("bitDSP_int32.lib"); 10 | 11 | // plot 12 | // CXXFLAGS="-I ../include" faust2csvplot -I ../lib lfsr32.dsp 13 | // ./lfsr32 -n 10 14 | 15 | // compile 16 | // CXXFLAGS="-I ../../../include" faust2caqt -I ../lib lfsr32.dsp 17 | // // open lfsr32.app 18 | 19 | dac_bits = int(nentry("dac bits" ,1,1,32,1)); 20 | dac_offset = min(int(nentry("dac offset",0,0,31,1)), 32-dac_bits); 21 | 22 | // initial state of the LFSR (!=0) 23 | // change to reset LFSR to start with that new value 24 | lfsr_init = nentry("init val",1,1,492000,1); 25 | 26 | // set your own bits 27 | // lfsr_mask = bit32.bit_mask( 28 | // par(i,6, 29 | // nentry("parity source bit %i",i,0,31,1) 30 | // ) 31 | // ); 32 | // an example that reasonable sense... 33 | lfsr_mask = bit32.bit_mask((8, 31, 10)); // bits to set high 34 | 35 | // lfsr = bit32.lfsr32(lfsr_mask, lfsr_init) <: _,_; 36 | lfsr = bit32.lfsr32(lfsr_mask, lfsr_init); 37 | 38 | // select which bit range should be used to create the PCM signal 39 | process = lfsr : par(i, outputs(lfsr), bit32.bitDAC(dac_offset, dac_bits)); 40 | -------------------------------------------------------------------------------- /examples/bitRot.dsp: -------------------------------------------------------------------------------- 1 | declare name "bitRot"; 2 | declare description "bitRot - example"; 3 | declare author "Till Bovermann"; 4 | declare reference "http://rottingsounds.org"; 5 | 6 | import("stdfaust.lib"); 7 | bit = library("bitDSP.lib"); 8 | 9 | // plot 10 | // CXXFLAGS="-I ../include" faust2csvplot -I ../lib bitRot.dsp 11 | // ./bitRot -n 10 12 | 13 | // compile 14 | // CXXFLAGS="-I ../../../include" faust2caqt -I ../lib bitRot.dsp 15 | // ./bitRot 16 | 17 | 18 | 19 | /////////////////////////// UI //////////////////////////////// 20 | chance = hslider("chance", 0, 0, 1, 0.0001); 21 | type = hslider("type" , 1, 1, 3, 1); 22 | amp = hslider("amp" , 0, 0, 1, 0.001) : si.smoo; 23 | 24 | 25 | /////////////////////////// Input ///////////////////////////// 26 | bitSin = bit.ddsm1(os.osc(50)); 27 | dirac = 1 - 1'; 28 | silence = fbPath(dirac) ~ _ with { 29 | fbPath(init, fb) = -fb + init; 30 | }; 31 | 32 | // noise needs to be unimodal 33 | noise = (no.noise + 1) * 0.5; 34 | 35 | // process = bitSin <: _, bitrot(noise, chance, type) : bit2mbit, bit2mbit with { 36 | // bit2mbit(x) = fi.lowpass(4, 4000, x); 37 | // }; 38 | 39 | 40 | process = bitSin : bit.bitrot(noise, chance, type) : outPCM(2, amp) with { 41 | outPCM(N, amp, x) = fi.lowpass(2, 4000, x) * amp : leakdc(0.999) <: si.bus(N); 42 | leakdc(coef, x) = y letrec { 43 | 'y = x - x' + coef * y; 44 | }; 45 | }; 46 | 47 | -------------------------------------------------------------------------------- /examples/lfsrNoGUI.dsp: -------------------------------------------------------------------------------- 1 | declare name "LFSRNoGUI"; 2 | declare description "linear feedback shift register example without GUI"; 3 | declare author "Till Bovermann"; 4 | declare reference "http://rottingsounds.org"; 5 | // see https://en.wikipedia.org/wiki/Linear-feedback_shift_register 6 | 7 | import("stdfaust.lib"); 8 | bit32 = library("bitDSP_int32.lib"); 9 | 10 | // plot 11 | // CXXFLAGS="-I ../include" faust2csvplot -I ../lib lfsrNoGUI.dsp 12 | // ./lfsrNoGUI -n 10 13 | 14 | // compile 15 | // CXXFLAGS="-I ../../../include" faust2caqt -I ../lib lfsrNoGUI.dsp 16 | // // open lfsrNoGUI.app 17 | 18 | // dac_bits = int(nentry("dac bits",1,1,32,1)); 19 | // dac_offset = min(int(nentry("dac offset",0,0,31,1)), 32-dac_bits); 20 | dac_bits = 31; 21 | dac_offset = 0; 22 | 23 | // lfsr_bits = int(nentry("lfsr bits",1,1,32,1)); 24 | lfsr_bits = 16; 25 | // lfsr_init = nentry("init val",1,1,492000,1); 26 | lfsr_init = 12356; 27 | // lfsr_mask = bit32.bit_mask( 28 | // par(i,6, 29 | // nentry("parity source bit %i",i,0,31,1) 30 | // ) 31 | // ); 32 | lfsr_mask = bit32.bit_mask((15, 13, 11, 10, 2)); 33 | 34 | 35 | lfsr = ( 36 | bit32.lfsr(lfsr_bits, lfsr_mask, lfsr_init), 37 | bit32.lfsr(lfsr_bits, lfsr_mask, lfsr_init + 1) 38 | ); 39 | 40 | // select which bit range should be used to create the PCM signal 41 | process = lfsr : par(i, outputs(lfsr), bit32.bitDAC(dac_offset, dac_bits)); 42 | -------------------------------------------------------------------------------- /examples/_sc/RawLFSR.dsp: -------------------------------------------------------------------------------- 1 | declare name "RawLFSR"; 2 | declare author "Till Bovermann"; 3 | declare description "linear feedback shift register example, raw output"; 4 | declare reference "http://rottingsounds.org"; 5 | // compute lfsr on an n-bit integer bitset (assuming it to be unsigned, [0 < n <= 32] ). 6 | // see https://en.wikipedia.org/wiki/Linear-feedback_shift_register 7 | 8 | import("stdfaust.lib"); 9 | bit32 = library("bitDSP_int32.lib"); 10 | 11 | // SuperCollider 12 | // CXXFLAGS="-I ../../../../include" faust2supercollider -I ../../lib -noprefix RawLFSR.dsp 13 | 14 | // plot 15 | // CXXFLAGS="-I ../include" faust2csvplot -I ../../lib RawLFSR.dsp 16 | // ./lfsr -n 10 17 | 18 | // compile 19 | // CXXFLAGS="-I ../../../include" faust2caqt -I ../../lib RawLFSR.dsp 20 | // // open lfsr.app 21 | 22 | 23 | // how many bits the LFSR runs on (1-32) 24 | lfsr_num_bits = int(nentry("bits",1,1,32,1)); 25 | 26 | // initial state of the LFSR as 32bit (!=0) 27 | // change to reset LFSR to start with that new value 28 | lfsr_init_state = nentry("init",1,1,492000,1); 29 | lfsr_parity_mask = bit32.bit_mask( 30 | par(i,32, 31 | nentry("bit%i",i,0,31,1) 32 | ) 33 | ); 34 | 35 | 36 | // lfsr = ( 37 | // bit32.lfsr(lfsr_num_bits, lfsr_parity_mask, lfsr_init_state), 38 | // bit32.lfsr(lfsr_num_bits, lfsr_parity_mask, lfsr_init_state + 1) 39 | // ); 40 | 41 | lfsr = bit32.lfsr(lfsr_num_bits, lfsr_parity_mask, lfsr_init_state); 42 | 43 | process = lfsr; 44 | -------------------------------------------------------------------------------- /examples/lfsr.dsp: -------------------------------------------------------------------------------- 1 | declare name "LFSR"; 2 | declare author "Till Bovermann"; 3 | declare description "linear feedback shift register example"; 4 | declare reference "http://rottingsounds.org"; 5 | // compute lfsr on an n-bit integer bitset (assuming it to be unsigned, [0 < n <= 32] ). 6 | // see https://en.wikipedia.org/wiki/Linear-feedback_shift_register 7 | 8 | import("stdfaust.lib"); 9 | bit32 = library("bitDSP_int32.lib"); 10 | 11 | // plot 12 | // CXXFLAGS="-I ../include" faust2csvplot -I ../lib lfsr.dsp 13 | // ./lfsr -n 10 14 | 15 | // compile 16 | // CXXFLAGS="-I ../../../include" faust2caqt -I ../lib lfsr.dsp 17 | // // open lfsr.app 18 | 19 | dac_bits = int(nentry("dac bits",1,1,32,1)); 20 | dac_offset = min(int(nentry("dac offset",0,0,31,1)), 32-dac_bits); 21 | 22 | 23 | // how many bits the LFSR runs on (1-32) 24 | lfsr_num_bits = int(nentry("lfsr bits",1,1,32,1)); 25 | 26 | // initial state of the LFSR as 32bit (!=0) 27 | // change to reset LFSR to start with that new value 28 | lfsr_init_state = nentry("init val",1,1,492000,1); 29 | lfsr_parity_mask = bit32.bit_mask( 30 | par(i,6, 31 | nentry("parity source bit %i",i,0,31,1) 32 | ) 33 | ); 34 | 35 | 36 | lfsr = ( 37 | bit32.lfsr(lfsr_num_bits, lfsr_parity_mask, lfsr_init_state), 38 | bit32.lfsr(lfsr_num_bits, lfsr_parity_mask, lfsr_init_state + 1) 39 | ); 40 | 41 | // select which bit range should be used to create the PCM signal 42 | process = lfsr : par(i, outputs(lfsr), bit32.bitDAC(dac_offset, dac_bits)); 43 | -------------------------------------------------------------------------------- /include/bitDSP.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #ifndef bitdsp_h 7 | #define bitdsp_h 8 | 9 | typedef std::bitset<32> bit32; 10 | 11 | // int bit_shift(int last, int current, int amount) { 12 | // if (amount < 1) 13 | // { 14 | // return current; 15 | // } 16 | // if (amount >= 32) 17 | // { 18 | // return last; 19 | // } 20 | // return ((current >> amount) | (last << (32-amount))); 21 | // } 22 | 23 | int bit_not(int x) { 24 | return ~x; 25 | } 26 | 27 | int div_i(int x, int y) { 28 | return x/y; 29 | } 30 | 31 | int bit_print(int in) { 32 | std::cout << bit32(in) << '\n'; 33 | return in; 34 | } 35 | 36 | int bit_print2counters(int counter1, int counter2, int in) { 37 | std::cout << "(" << std::setfill('0') << std::setw(3) << counter1 << '\t' << std::setfill('0') << std::setw(3) << counter2 << ")\t" << bit32(in) << '\n'; 38 | return in; 39 | } 40 | 41 | int bit_leftShift(int a, int b) { 42 | return (int) ((uint32_t) a << (uint32_t) b); 43 | } 44 | 45 | int bit_rightShift(int a, int b) { 46 | return (int) ((uint32_t) a >> (uint32_t) b); 47 | } 48 | 49 | 50 | int parity (int in) { 51 | // find parity of 32bit uint, 52 | // adapted from https://graphics.stanford.edu/~seander/bithacks.html#ParityParallel 53 | 54 | uint32_t ui_op = (uint32_t) in; 55 | ui_op ^= ui_op >> 16; 56 | ui_op ^= ui_op >> 8; 57 | ui_op ^= ui_op >> 4; 58 | ui_op &= 0xf; 59 | return (int) ((0x6996 >> ui_op) & 1); 60 | } 61 | 62 | 63 | 64 | #endif 65 | -------------------------------------------------------------------------------- /examples/_sc/lfsr.dsp: -------------------------------------------------------------------------------- 1 | declare name "LFSR"; 2 | declare author "Till Bovermann"; 3 | declare description "linear feedback shift register example"; 4 | declare reference "http://rottingsounds.org"; 5 | // compute lfsr on an n-bit integer bitset (assuming it to be unsigned, [0 < n <= 32] ). 6 | // see https://en.wikipedia.org/wiki/Linear-feedback_shift_register 7 | 8 | import("stdfaust.lib"); 9 | bit32 = library("bitDSP_int32.lib"); 10 | 11 | // SuperCollider 12 | // CXXFLAGS="-I ../../../../include" faust2supercollider -d -I ../lib -noprefix lfsr32.dsp 13 | 14 | // plot 15 | // CXXFLAGS="-I ../include" faust2csvplot -I ../lib lfsr.dsp 16 | // ./lfsr -n 10 17 | 18 | // compile 19 | // CXXFLAGS="-I ../../../include" faust2caqt -I ../lib lfsr.dsp 20 | // // open lfsr.app 21 | 22 | dac_bits = int(nentry("dacBits",1,1,32,1)); 23 | dac_offset = min(int(nentry("dacOffset",0,0,31,1)), 32-dac_bits); 24 | 25 | 26 | // how many bits the LFSR runs on (1-32) 27 | lfsr_num_bits = int(nentry("lfsrBits",1,1,32,1)); 28 | 29 | // initial state of the LFSR as 32bit (!=0) 30 | // change to reset LFSR to start with that new value 31 | lfsr_init_state = nentry("init",1,1,492000,1); 32 | lfsr_parity_mask = bit32.bit_mask( 33 | par(i,32, 34 | nentry("pBit%i",i,0,31,1) 35 | ) 36 | ); 37 | 38 | 39 | // lfsr = ( 40 | // bit32.lfsr(lfsr_num_bits, lfsr_parity_mask, lfsr_init_state), 41 | // bit32.lfsr(lfsr_num_bits, lfsr_parity_mask, lfsr_init_state + 1) 42 | // ); 43 | 44 | lfsr = bit32.lfsr(lfsr_num_bits, lfsr_parity_mask, lfsr_init_state); 45 | 46 | // select which bit range should be used to create the PCM signal 47 | process = lfsr : par(i, outputs(lfsr), bit32.bitDAC(dac_offset, dac_bits)); 48 | -------------------------------------------------------------------------------- /lib/bandpass.lib: -------------------------------------------------------------------------------- 1 | svf2blti(cf, q, k, in) = tick 2 | ~ ( _ , 3 | _) : ( ! , 4 | ! , 5 | _ , 6 | _ , 7 | _ , 8 | _ , 9 | _ , 10 | _ , 11 | _ , 12 | _ , 13 | _ , 14 | _) 15 | with { 16 | div(x1, x2) = x1 / ba.if( x2 < 0, 17 | min(ma.EPSILON * -1, x2), 18 | max(ma.EPSILON, x2)); 19 | w(f) = 2 * ma.PI * f / ma.SR; 20 | r = div(1, (2 * q)); 21 | wa = (2 * ma.SR) * tan(w(cf) / 2); 22 | g = wa / ma.SR / 2; 23 | tick(s1, s2) = u1 , 24 | u2 , 25 | lp , 26 | hp , 27 | bp , 28 | bp_norm , 29 | ls , 30 | hs , 31 | b_shelf , 32 | notch , 33 | peak , 34 | ap 35 | with { 36 | u1 = v1 + bp; 37 | u2 = v2 + lp; 38 | v1 = hp * g; 39 | v2 = bp * g; 40 | hp = div((in - 2 * r * s1 - g * s1 - s2), 41 | (1 + 2 * r * g + g * g)); 42 | bp = s1 + v1; 43 | lp = s2 + v2; 44 | bp_norm = bp * 2 * r; 45 | b_shelf = in + k * bp_norm; 46 | ls = in + k * lp; 47 | hs = in + k * hp; 48 | notch = in - bp_norm; 49 | ap = in - 4 * r * bp; 50 | peak = lp - hp; 51 | }; 52 | }; 53 | bp(cf, q, x) = svf2blti(cf, q, 1, x) : ba.selectn(10,3); 54 | 55 | -------------------------------------------------------------------------------- /examples/_sc/BoolOscFB.dsp: -------------------------------------------------------------------------------- 1 | declare name "BoolOscFB"; 2 | declare description "bool_osc FB"; 3 | declare author "Till Bovermann"; 4 | declare reference "http://rottingsounds.org"; 5 | 6 | import("stdfaust.lib"); 7 | bit = library("bitDSP.lib"); 8 | 9 | 10 | // SuperCollider 11 | // CXXFLAGS="-I ../../../../include" faust2supercollider -I ../../lib -noprefix BoolOscFB.dsp 12 | 13 | // plot 14 | // CXXFLAGS="-I ../include" faust2csvplot -I ../lib boolOsc_fb.dsp 15 | // ./boolOsc_fb -n 10 16 | 17 | // compile 18 | // CXXFLAGS="-I ../../../include" faust2caqt -I ../lib boolOsc_fb.dsp 19 | // ./boolOsc_fb 20 | 21 | 22 | // bool_osc1(del1, del2) = node1 23 | // letrec { 24 | // 'node1 = not(node1 xor node2 & node1) @ max(0, min(ma.SR, del1)); 25 | // 'node2 = not(node2 xor node1 xor node2) @ max(0, min(ma.SR, del2)); 26 | // } 27 | // with { 28 | // not(x) = 1 - x; 29 | // }; 30 | 31 | 32 | // bool_osc2(del1, del2) = node1 33 | 34 | // letrec { 35 | // 'node1 = not(node1 & node2) @ max(0, min(ma.SR, del1)); 36 | // 'node2 = not(node1 & node2) @ max(0, min(ma.SR, del2)); 37 | // } 38 | // with { 39 | // not(x) = rint(1 - x); 40 | // }; 41 | 42 | 43 | 44 | // lp1p (Dario) 45 | // One-pole lowpass (design by Chamberlin). 46 | // 47 | // 2 inputs: 48 | // CF[n], cut-off frequency in Hz; 49 | // x[n]. 50 | // 51 | // 1 outputs: 52 | // y[n], lowpassed x[n]. 53 | lp1p(cf, in) = + (in * a0) ~ * (b1) with { 54 | a0 = 1 - b1; 55 | b1 = exp(w(cf) * -1); 56 | w(x) = x * twopi / ma.SR; 57 | twopi = 2 * ma.PI; 58 | }; 59 | 60 | // rms (dario) 61 | rms(window, in) = in <: * : lp1p(window) : sqrt; 62 | 63 | 64 | // sc-like leakdc 65 | leakdc(coef, x) = y letrec { 66 | 'y = x - x' + coef * y; 67 | }; 68 | 69 | 70 | feedbackOsc(cutoff, dt1, dt2, leakcoef, att,rel) = loop ~ (_, _) with { 71 | loop(fb1, fb2) = 72 | bit.bool_osc1(amp(fb2), amp(fb1))@(dt1), 73 | (bit.bool_osc2(amp(fb1), amp(fb2))@(dt2)); 74 | rmsN(sig) = leakdc(leakcoef, rms(cutoff, sig)); 75 | amp(sig) = 40 * leakdc(leakcoef, sig) : an.amp_follower_ud(att,rel); 76 | // amp(sig) = leakdc(leakcoef, sig) : an.amp_follower(att); 77 | }; 78 | 79 | 80 | 81 | dt1 = hslider("dt1",0,0,20000,1); 82 | dt2 = hslider("dt2",0,0,20000,1); 83 | cutoff = hslider("cutoff",100,100,1000,0); 84 | leakcoef = hslider("leakcoef",0.99,0.99, 1, 0.000001); 85 | att = hslider("att",0,0, 1, 0.000001); 86 | rel = hslider("rel",0,0, 1, 0.000001); 87 | 88 | // stereo out 89 | process = feedbackOsc(cutoff, dt1, dt2, leakcoef, att, rel); 90 | // process = leakdc(leakcoef, os.impulse); -------------------------------------------------------------------------------- /examples/_sc/BoolOscFB1.dsp: -------------------------------------------------------------------------------- 1 | declare name "BoolOscFB1"; 2 | declare description "bool_osc FB alternative 1"; 3 | declare author "Till Bovermann"; 4 | declare reference "http://rottingsounds.org"; 5 | 6 | import("stdfaust.lib"); 7 | // bit = library("bitDSP.lib"); 8 | 9 | 10 | // SuperCollider 11 | // CXXFLAGS="-I ../../../../include" faust2supercollider -I ../../lib -noprefix BoolOscFB1.dsp 12 | 13 | // plot 14 | // CXXFLAGS="-I ../include" faust2csvplot -I ../lib boolOsc_fb.dsp 15 | // ./boolOsc_fb -n 10 16 | 17 | // compile 18 | // CXXFLAGS="-I ../../../include" faust2caqt -I ../lib boolOsc_fb.dsp 19 | // ./boolOsc_fb 20 | 21 | 22 | bool_osc1_mod(del1, del2) = node1 letrec { 23 | 'node1 = not(node1 xor node2 & node1) @ min(ma.SR,(del1 % ma.SR)); 24 | 'node2 = not(node2 xor node1 xor node2) @ min(ma.SR,(del2 % ma.SR)); 25 | } with { 26 | not(x) = 1 - x; 27 | }; 28 | 29 | 30 | bool_osc2_mod(del1, del2) = node1 letrec { 31 | 'node1 = not(node1 & node2) @ min(ma.SR,(del1 % ma.SR)); 32 | 'node2 = not(node1 & node2) @ min(ma.SR,(del2 % ma.SR)); 33 | } with { 34 | not(x) = rint(1 - x); 35 | }; 36 | 37 | 38 | oscfb1(leakcoef, bias1, bias2, mod1, mod2) = loop ~ _ with { 39 | loop(fb) = bool_osc1_mod( 40 | (fb : map(bias1, mod2)), 41 | (fb : map(bias2, mod1)) 42 | ) : leakdc(leakcoef); 43 | }; 44 | oscfb2(leakcoef, bias1, bias2, mod1, mod2) = loop ~ _ with { 45 | loop(fb) = bool_osc2_mod( 46 | (fb : map(bias1, mod1)), 47 | (fb : map(bias2, mod2)) 48 | ) : leakdc(leakcoef); 49 | }; 50 | 51 | map(bias, scale, in) = max(0, (bias * biasfac) + (scale * in * modfac)) with { 52 | biasfac = 15000; 53 | modfac = 15000; 54 | }; 55 | 56 | 57 | // sc-like leakdc 58 | leakdc(coef, x) = y letrec { 59 | 'y = x - x' + coef * y; 60 | }; 61 | 62 | // MS processor 63 | // ms(x, y, width) = (x + y) * 0.5, (x-y) * 0.5 * width; 64 | ms(1, midIn, sideIn) = (midIn + sideIn) * 0.5, (midIn-sideIn) * 0.5; 65 | ms(width, midIn, sideIn) = (mid + side) * 0.5, (mid-side) * 0.5 with { 66 | mid = midIn; 67 | side = sideIn * width; 68 | }; 69 | 70 | 71 | rotate2(r, x, y) = xout, yout with { 72 | xout = cos(r) * x + sin(r) * y; 73 | yout = cos(r) * y - sin(r) * x; 74 | }; 75 | 76 | // stereo out 77 | process = 78 | oscfb1(leakcoef, bias1, bias2, mod1, mod2), 79 | oscfb2(leakcoef, bias1, bias2, mod1, mod2) 80 | : leak 81 | : rotate2(rot) 82 | : ms(1) : ms(width) 83 | : vca(distort) 84 | : tanh 85 | : vca(amp) 86 | : fi.lowpass(lporder, lpfreq), fi.lowpass(lporder, lpfreq) 87 | <: si.bus(2) 88 | with { 89 | 90 | distort = hslider("m_distort[scale:exp]", 1, 1, 100, 0.001) : si.smoo; 91 | amp = hslider("m_amp", 0, 0, 4, 0.001) : si.smoo; 92 | width = hslider("m_width", 0, 0, 1, 0.001) : si.smoo; 93 | rot = hslider("m_rot", 0, 0, 1, 0.001) : si.smoo * ma.PI; 94 | lpfreq = hslider("m_lpfreq[scale:exp]", 2400, 10, 20000, 1) : si.smoo; 95 | 96 | coef_in = hslider("d_leak", 0, 0, 1, 0.0001) : si.smoo; 97 | leakcoef = 1 - (coef_in * 0.001); 98 | 99 | mod1 = hslider("d_mod1[scale:exp]", 0.0001, 0.0001, 1, 0.00001) : si.smoo; 100 | mod2 = hslider("d_mod2[scale:exp]", 0.0001, 0.0001, 1, 0.00001) : si.smoo; 101 | bias1 = hslider("d_bias1[scale:exp]", 0.0001, 0.0001, 1, 0.00001) : si.smoo; 102 | bias2 = hslider("d_bias2[scale:exp]", 0.0001, 0.0001, 1, 0.00001) : si.smoo; 103 | lporder = 4; 104 | tanh = ma.tanh(_), ma.tanh(_); 105 | leak = leakdc(0.999), leakdc(0.999); 106 | 107 | vca(amp) = _ * amp, _ * amp; 108 | 109 | 110 | }; 111 | 112 | 113 | 114 | // process = ma.SR / 100000; -------------------------------------------------------------------------------- /synths/BoolOscFB1.dsp: -------------------------------------------------------------------------------- 1 | declare name "BoolOscFB1"; 2 | declare description "bool_osc FB alternative 1"; 3 | declare author "Till Bovermann"; 4 | declare reference "http://rottingsounds.org"; 5 | 6 | import("stdfaust.lib"); 7 | // bit = library("bitDSP.lib"); 8 | 9 | 10 | // SuperCollider 11 | // CXXFLAGS="-I ../../../../include" faust2supercollider -I ../../lib -noprefix BoolOscFB1.dsp 12 | 13 | // plot 14 | // CXXFLAGS="-I ../include" faust2csvplot -I ../lib boolOsc_fb.dsp 15 | // ./boolOsc_fb -n 10 16 | 17 | // compile 18 | // CXXFLAGS="-I ../../../include" faust2caqt -I ../lib boolOsc_fb.dsp 19 | // ./boolOsc_fb 20 | 21 | 22 | // bool_osc1_mod(del1, del2) = node1 letrec { 23 | // 'node1 = not(node1 xor node2 & node1) @ min(maxDel,(del1 % maxDel)); 24 | // 'node2 = not(node2 xor node1 xor node2) @ min(maxDel,(del2 % maxDel)); 25 | // }; 26 | 27 | 28 | // bool_osc2_mod(del1, del2) = node1 letrec { 29 | // 'node1 = not(node1 & node2) @ min(maxDel,(del1 % maxDel)); 30 | // 'node2 = not(node1 & node2) @ min(maxDel,(del2 % maxDel)); 31 | // }; 32 | 33 | bool_osc1_mod(d1, d2) = node1 letrec { 34 | 'node1 = delay(d1, not(node1 xor node2 & node1)); 35 | 'node2 = delay(d2, not(node2 xor node1 xor node2)); 36 | }; 37 | 38 | 39 | bool_osc2_mod(d1, d2) = node1 letrec { 40 | 'node1 = delay(d1, not(node1 & node2)); 41 | 'node2 = delay(d2, not(node1 & node2)); 42 | }; 43 | 44 | 45 | 46 | 47 | delay(d, x) = de.delay(maxDel, (d % maxDel), x); 48 | not(x) = rint(1 - x); 49 | maxDel = ma.SR / 4; 50 | 51 | 52 | oscfb1(leakcoef, bias1, bias2, mod1, mod2) = loop ~ _ with { 53 | loop(fb) = bool_osc1_mod( 54 | (fb : map(bias1, mod2)), 55 | (fb : map(bias2, mod1)) 56 | ) : leakdc(leakcoef); 57 | }; 58 | 59 | oscfb2(leakcoef, bias1, bias2, mod1, mod2) = loop ~ _ with { 60 | loop(fb) = bool_osc2_mod( 61 | (fb : map(bias1, mod1)), 62 | (fb : map(bias2, mod2)) 63 | ) : leakdc(leakcoef); 64 | }; 65 | 66 | map(bias, scale, in) = max(0, (bias * biasfac) + (scale * in * modfac)) with { 67 | biasfac = 15000; 68 | modfac = 15000; 69 | }; 70 | 71 | 72 | // sc-like leakdc 73 | leakdc(coef, x) = y letrec { 74 | 'y = x - x' + coef * y; 75 | }; 76 | 77 | // MS processor 78 | // ms(x, y, width) = (x + y) * 0.5, (x-y) * 0.5 * width; 79 | ms(1, midIn, sideIn) = (midIn + sideIn) * 0.5, (midIn-sideIn) * 0.5; 80 | ms(width, midIn, sideIn) = (mid + side) * 0.5, (mid-side) * 0.5 with { 81 | mid = midIn; 82 | side = sideIn * width; 83 | }; 84 | 85 | 86 | rotate2(r, x, y) = xout, yout with { 87 | xout = cos(r) * x + sin(r) * y; 88 | yout = cos(r) * y - sin(r) * x; 89 | }; 90 | 91 | // stereo out 92 | process = ( 93 | oscfb1(leakcoef, bias1, bias2, mod1, mod2), 94 | oscfb2(leakcoef, bias1, bias2, mod1, mod2) 95 | ) 96 | : leakDC 97 | : rotate2(rot) 98 | : ms(1) : ms(width) 99 | : vca(distort) 100 | : tanh 101 | : vca(amp) 102 | : fi.lowpass(lporder, lpfreq), fi.lowpass(lporder, lpfreq) 103 | // <: si.bus(2) 104 | with { 105 | mod1 = hslider("[01]mod1[scale:exp]", 0.0001, 0.0001, 1, 0.00001) : si.smoo; 106 | mod2 = hslider("[02]mod2[scale:exp]", 0.0001, 0.0001, 1, 0.00001) : si.smoo; 107 | bias1 = hslider("[03]bias1[scale:exp]", 0.0001, 0.0001, 1, 0.00001) : si.smoo; 108 | bias2 = hslider("[04]bias2[scale:exp]", 0.0001, 0.0001, 1, 0.00001) : si.smoo; 109 | 110 | leak = hslider("[05]leak", 0.01, 0, 1, 0.0001) : si.smoo; 111 | leakcoef = 1 - (leak * 0.001); 112 | 113 | 114 | distort = hslider("[06]distort[scale:exp]", 1, 1, 10, 0.001) : si.smoo; 115 | amp = hslider("[07]amp", 0.5, 0, 1, 0.001) : si.smoo; 116 | 117 | width = hslider("[08]width", 1, 0, 1, 0.001) : si.smoo; 118 | rot = hslider("[09]rot", 0.25, 0, 1, 0.001) : si.smoo * ma.PI; 119 | lpfreq = hslider("[10]lpfreq[scale:exp]", 10000, 10, 20000, 1) : si.smoo; 120 | 121 | 122 | lporder = 4; 123 | tanh = ma.tanh(_), ma.tanh(_); 124 | leakDC = leakdc(0.999), leakdc(0.999); 125 | 126 | vca(amp) = _ * amp, _ * amp; 127 | 128 | 129 | }; 130 | -------------------------------------------------------------------------------- /synths/BoolOscFB3.dsp: -------------------------------------------------------------------------------- 1 | declare name "BoolOscFB1"; 2 | declare description "bool_osc FB alternative 1"; 3 | declare author "Till Bovermann"; 4 | declare reference "http://rottingsounds.org"; 5 | 6 | import("stdfaust.lib"); 7 | // bit = library("bitDSP.lib"); 8 | 9 | 10 | // SuperCollider 11 | // CXXFLAGS="-I ../../../../include" faust2supercollider -I ../../lib -noprefix BoolOscFB1.dsp 12 | 13 | // plot 14 | // CXXFLAGS="-I ../include" faust2csvplot -I ../lib boolOsc_fb.dsp 15 | // ./boolOsc_fb -n 10 16 | 17 | // compile 18 | // CXXFLAGS="-I ../../../include" faust2caqt -I ../lib boolOsc_fb.dsp 19 | // ./boolOsc_fb 20 | 21 | // sc-type mod (always >= 0) 22 | mod(a, 0) = 0; 23 | mod(a, b) = ba.if(a > 0, a % b, a % b + b); 24 | 25 | 26 | bool_osc1_mod(d1, d2) = node1 letrec { 27 | 'node1 = not(node1 xor node2 & node1) @ min(ma.SR,mod(d1, ma.SR)); 28 | 'node2 = not(node2 xor node1 xor node2) @ min(ma.SR,mod(d2, ma.SR)); 29 | } with { 30 | not(x) = rint(1 - x); 31 | }; 32 | 33 | 34 | bool_osc2_mod(d1, d2) = node1 letrec { 35 | 'node1 = not(node1 & node2) @ min(ma.SR,mod(d1, ma.SR)); 36 | 'node2 = not(node1 & node2) @ min(ma.SR,mod(d2, ma.SR)); 37 | } with { 38 | not(x) = rint(1 - x); 39 | }; 40 | 41 | // bitrot(noise, chance, type) = _ <: select3(type-1, low(noise, chance, _), flip(noise, chance, _), high(noise, chance, _)) with { 42 | // low(noise, chance, x) = select2(coin(noise, chance), x, 0); 43 | // high(noise, chance, x) = select2(coin(noise, chance), x, 1); 44 | // flip(noise, chance, x) = select2(coin(noise, chance), x, 1-x); 45 | // coin(noise, chance) = noise < chance; 46 | // }; 47 | 48 | 49 | 50 | // rms (dario) 51 | rms(window, in) = in <: * : lp1p(window) : sqrt with { 52 | // lp1p (Dario) 53 | // One-pole lowpass (design by Chamberlin). 54 | lp1p(cf, in) = + (in * a0) ~ * (b1) with { 55 | a0 = 1 - b1; 56 | b1 = exp(w(cf) * -1); 57 | w(x) = x * twopi / ma.SR; 58 | twopi = 2 * ma.PI; 59 | }; 60 | }; 61 | 62 | 63 | // sc-like leakdc 64 | leakdc(coef, x) = y letrec { 65 | 'y = x - x' + coef * y; 66 | }; 67 | 68 | 69 | selectx(which, x, y) = (which * x) + ((1-which) * y); 70 | 71 | // MS processor 72 | ms(width, x, y) = (x + y) * 0.5, (x-y) * 0.5 * width; 73 | 74 | 75 | 76 | coef_in = hslider("coefIn", 0, 0, 1, 0.0001) : si.smoo; 77 | d11bias = hslider("d11bias", 24, 0, 2000, 1); 78 | d11 = hslider("d11", 95/1000, 0, 1, 0.0001) : si.smoo; 79 | d12bias = hslider("d12bias", 49, 0, 2000, 1); 80 | d12 = hslider("d12", 116/1000, 0, 1, 0.0001) : si.smoo; 81 | 82 | d21bias = hslider("d21bias", 24, 0, 2000, 1); 83 | d21 = hslider("d21", 95/1000, 0, 1, 0.0001) : si.smoo; 84 | d22bias = hslider("d22bias", 49, 0, 2000, 1); 85 | d22 = hslider("d22", 116/1000, 0, 1, 0.0001) : si.smoo; 86 | 87 | lpfreq = hslider("lpfreq", 2400, 0, 10000, 1) : si.smoo; 88 | lporder = 5; // low=pass order 89 | amp = hslider("amp", 0, 0, 1, 0.01) : si.smoo; 90 | 91 | xfb = hslider("xfb", 0, 0, 1, 0.01) : si.smoo; 92 | 93 | 94 | // d1 = 0.03843526787654; 95 | // d2 = 0.421234567658; 96 | // d1off = 280; 97 | // d2off = 334; 98 | 99 | 100 | // stereo out 101 | process = oscfb(leakcoef, xfb, d11bias, d11, d12bias, d12, d21bias, d21, d22bias, d22) 102 | : leakdc(0.99999), leakdc(0.99999) 103 | : ms(1) 104 | : fi.lowpass(lporder, lpfreq), fi.lowpass(lporder, lpfreq) 105 | : _ * amp, _ * amp 106 | with { 107 | leakcoef = 1 - ((1-coef_in) * 0.0001); 108 | 109 | oscfb(leakcoef, xfb, d11bias, d11, d12bias, d12, d21bias, d21, d22bias, d22) = (loop ~ (_, _)) with { 110 | loop(fb1, fb2) = 111 | loop1( 112 | selectx(xfb, fb1, fb2), 113 | leakcoef, 114 | d11bias, d11, 115 | d12bias, d12 116 | ), 117 | loop2( 118 | selectx(xfb, fb2, fb1), 119 | leakcoef, 120 | d21bias, d21, 121 | d22bias, d22 122 | ); 123 | 124 | loop1(fb, coef, d1off, d1, d2off, d2) = 125 | bool_osc1_mod( 126 | max(0, d1off + (fb * 5000 * d1)), 127 | max(0, d2off + (fb * 5000 * d2)) 128 | ) 129 | : leakdc(coef); 130 | loop2(fb, coef, d1off, d1, d2off, d2) = 131 | bool_osc2_mod( 132 | max(0, d1off + (fb * 5000 * d1)), 133 | max(0, d2off + (fb * 5000 * d2)) 134 | ) 135 | : leakdc(coef); 136 | }; 137 | }; 138 | -------------------------------------------------------------------------------- /examples/_sc/BoolOscFB3.dsp: -------------------------------------------------------------------------------- 1 | declare name "BoolOscFB1"; 2 | declare description "bool_osc FB alternative 1"; 3 | declare author "Till Bovermann"; 4 | declare reference "http://rottingsounds.org"; 5 | 6 | import("stdfaust.lib"); 7 | // bit = library("bitDSP.lib"); 8 | 9 | 10 | // SuperCollider 11 | // CXXFLAGS="-I ../../../../include" faust2supercollider -I ../../lib -noprefix BoolOscFB1.dsp 12 | 13 | // plot 14 | // CXXFLAGS="-I ../include" faust2csvplot -I ../lib boolOsc_fb.dsp 15 | // ./boolOsc_fb -n 10 16 | 17 | // compile 18 | // CXXFLAGS="-I ../../../include" faust2caqt -I ../lib boolOsc_fb.dsp 19 | // ./boolOsc_fb 20 | 21 | // sc-type mod (always >= 0) 22 | mod(a, 0) = 0; 23 | mod(a, b) = ba.if(a > 0, a % b, a % b + b); 24 | 25 | 26 | bool_osc1_mod(d1, d2) = node1 letrec { 27 | 'node1 = not(node1 xor node2 & node1) @ min(ma.SR,mod(d1, ma.SR)); 28 | 'node2 = not(node2 xor node1 xor node2) @ min(ma.SR,mod(d2, ma.SR)); 29 | } with { 30 | not(x) = rint(1 - x); 31 | }; 32 | 33 | 34 | bool_osc2_mod(d1, d2) = node1 letrec { 35 | 'node1 = not(node1 & node2) @ min(ma.SR,mod(d1, ma.SR)); 36 | 'node2 = not(node1 & node2) @ min(ma.SR,mod(d2, ma.SR)); 37 | } with { 38 | not(x) = rint(1 - x); 39 | }; 40 | 41 | // bitrot(noise, chance, type) = _ <: select3(type-1, low(noise, chance, _), flip(noise, chance, _), high(noise, chance, _)) with { 42 | // low(noise, chance, x) = select2(coin(noise, chance), x, 0); 43 | // high(noise, chance, x) = select2(coin(noise, chance), x, 1); 44 | // flip(noise, chance, x) = select2(coin(noise, chance), x, 1-x); 45 | // coin(noise, chance) = noise < chance; 46 | // }; 47 | 48 | 49 | 50 | // rms (dario) 51 | rms(window, in) = in <: * : lp1p(window) : sqrt with { 52 | // lp1p (Dario) 53 | // One-pole lowpass (design by Chamberlin). 54 | lp1p(cf, in) = + (in * a0) ~ * (b1) with { 55 | a0 = 1 - b1; 56 | b1 = exp(w(cf) * -1); 57 | w(x) = x * twopi / ma.SR; 58 | twopi = 2 * ma.PI; 59 | }; 60 | }; 61 | 62 | 63 | // sc-like leakdc 64 | leakdc(coef, x) = y letrec { 65 | 'y = x - x' + coef * y; 66 | }; 67 | 68 | 69 | selectx(which, x, y) = (which * x) + ((1-which) * y); 70 | 71 | // MS processor 72 | ms(width, x, y) = (x + y) * 0.5, (x-y) * 0.5 * width; 73 | 74 | 75 | 76 | coef_in = hslider("coefIn", 0, 0, 1, 0.0001) : si.smoo; 77 | d11bias = hslider("d11bias", 24, 0, 2000, 1); 78 | d11 = hslider("d11", 95/1000, 0, 1, 0.0001) : si.smoo; 79 | d12bias = hslider("d12bias", 49, 0, 2000, 1); 80 | d12 = hslider("d12", 116/1000, 0, 1, 0.0001) : si.smoo; 81 | 82 | d21bias = hslider("d21bias", 24, 0, 2000, 1); 83 | d21 = hslider("d21", 95/1000, 0, 1, 0.0001) : si.smoo; 84 | d22bias = hslider("d22bias", 49, 0, 2000, 1); 85 | d22 = hslider("d22", 116/1000, 0, 1, 0.0001) : si.smoo; 86 | 87 | lpfreq = hslider("lpfreq", 2400, 0, 10000, 1) : si.smoo; 88 | lporder = 5; // low=pass order 89 | amp = hslider("amp", 0, 0, 1, 0.01) : si.smoo; 90 | 91 | xfb = hslider("xfb", 0, 0, 1, 0.01) : si.smoo; 92 | 93 | 94 | // d1 = 0.03843526787654; 95 | // d2 = 0.421234567658; 96 | // d1off = 280; 97 | // d2off = 334; 98 | 99 | 100 | // stereo out 101 | process = oscfb(leakcoef, xfb, d11bias, d11, d12bias, d12, d21bias, d21, d22bias, d22) 102 | : leakdc(0.99999), leakdc(0.99999) 103 | : ms(1) 104 | : fi.lowpass(lporder, lpfreq), fi.lowpass(lporder, lpfreq) 105 | : _ * amp, _ * amp 106 | with { 107 | leakcoef = 1 - ((1-coef_in) * 0.0001); 108 | 109 | oscfb(leakcoef, xfb, d11bias, d11, d12bias, d12, d21bias, d21, d22bias, d22) = (loop ~ (_, _)) with { 110 | loop(fb1, fb2) = 111 | loop1( 112 | selectx(xfb, fb1, fb2), 113 | leakcoef, 114 | d11bias, d11, 115 | d12bias, d12 116 | ), 117 | loop2( 118 | selectx(xfb, fb2, fb1), 119 | leakcoef, 120 | d21bias, d21, 121 | d22bias, d22 122 | ); 123 | 124 | loop1(fb, coef, d1off, d1, d2off, d2) = 125 | bool_osc1_mod( 126 | max(0, d1off + (fb * 5000 * d1)), 127 | max(0, d2off + (fb * 5000 * d2)) 128 | ) 129 | : leakdc(coef); 130 | loop2(fb, coef, d1off, d1, d2off, d2) = 131 | bool_osc2_mod( 132 | max(0, d1off + (fb * 5000 * d1)), 133 | max(0, d2off + (fb * 5000 * d2)) 134 | ) 135 | : leakdc(coef); 136 | }; 137 | }; 138 | -------------------------------------------------------------------------------- /works/BASP.dsp: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * BASP is a project for the creative use of bitstream musical DSP in Faust. 3 | * The work relies on a several library modules developed over almost a year 4 | * by Dario Sanfilippo and Till Bovermann. The library includes standard 5 | * functions for delta-sigma modulation and processing as well as original 6 | * algorithms for information processing and audio manipulation. 7 | * Part of the library modules are described in the following publication: 8 | * https://ifc20.sciencesconf.org/332745/document. 9 | * 10 | * The code below was developed by Dario Sanfilippo and it is a music 11 | * piece based on an adaptive, self-organising bitstream network. The work 12 | * includes four interdependent adaptive agents deploying different 13 | * techniques for the analysis, adaptation, and manipulation of single-bit 14 | * audio streams. 15 | * 16 | * Specifically, the adaptation infrastructure includes 17 | * statistical samplewise processing for the measurement of polarity 18 | * tendency, and an experimental algorithm for the approximation of 19 | * noisiness through fixed-latency autocorrelation. The adaptation mechanisms 20 | * operate both at timbral and formal time-scales for short and long-term 21 | * evolutions, and deploy hysteresis for low and high-level activation 22 | * functions for enhanced complexity. 23 | * 24 | * The algorithms for audio generation and manupilation include chaotic 25 | * self-oscillating systems based on bitwise operations, cross-coupled 26 | * delta-sigma filters, and nonlinear distortion through bitstream 27 | * audio pattern-matching. 28 | * 29 | * Even though the system has been designed to operate autonomously, the 30 | * user interface provides parameters to alter the adaptation infrustructure 31 | * to experience the work through different self-organising dynamics. 32 | * 33 | * PARAMETERS: 34 | * 35 | * - Gate de/activation rate (.001-.125 Hz): this parameter affects 36 | * affects the responsiveness of the statistical analysis that opens 37 | * and closes the outputs of the individual agents. The collective 38 | * behaviour of this gating de/activation results in an autonomous 39 | * regulation of the agents' presence over time. 40 | * 41 | * - Stepped changes rate (.001-.125 Hz): this parameter affects the 42 | * responsiveness of the adaptation mechanism dedicated to stepped 43 | * self-modulation. The input of each agent is analysed and the condition 44 | * to trigger a new parameter is given by a change of direction of the 45 | * signal, whereas the target value is determined by a time-variant 46 | * function that is given by integration of the magnitude of the 47 | * derivative. 48 | * 49 | * - Continuous changes rate (.001-.125 Hz): this parameter sets the 50 | * cut-off of a set of cascaded one-pole lowpass filters that act upon 51 | * the input signal of each agent. Slow cut-off values result in slower 52 | * continuous variations of the parameters, as the derivartive of the 53 | * input is decreased. 54 | * 55 | * - On/Off relay threshold: - these parameters set the lower and upper 56 | * boundaries of a one-bit hysteresis function, that is the deactivation 57 | * and activation thresholds, respectively. This hysteresis function 58 | * controls the parameter self-modulation modality: stepped, or continuous. 59 | * 60 | *******************************************************************************/ 61 | 62 | import("stdfaust.lib"); 63 | 64 | declare name "BASP – Boolean Audio Signal Processing"; 65 | declare author "Dario Sanfilippo"; 66 | declare copyright "Copyright (C) 2021 Dario Sanfilippo 67 | "; 68 | declare version "1.0"; 69 | declare license "MIT license"; 70 | 71 | bit = library("bitDSP.lib"); 72 | gen = library("bitDSP_gen.lib"); 73 | 74 | vol = hslider("[05]Vol", 0, 0, 1, .000001); 75 | stmix = si.bus(8) : par(i, 8, bit.meter(i, -60, 0)) :> si.bus(2) : par(i, 2, /(4) : bit.onebit2mbit * vol); 76 | 77 | gates = par(i, 8, bit.autogate(gate_rate)); 78 | params = par(i, 2, bit.autoparam(step_rate, incr_rate, alpha, beta) + init); 79 | 80 | init = .1890809373898301; 81 | 82 | gate_rate = hslider("[00]Gate de/activation rate (.001-.125 Hz)", .01, .001, .125, .000001); 83 | step_rate = hslider("[01]Stepped changes rate (.001-.125 Hz)", .01, .001, .125, .000001); 84 | incr_rate = hslider("[02]Continuous changes rate (.001-.125 Hz)", .01, .001, .125, .000001); 85 | 86 | alpha = hslider("[03]Off relay threshold", .3, 0, 1, .000001); 87 | beta = hslider("[04]On relay threshold", .7, 0, 1, .000001); 88 | 89 | circular = route(8, 8, (1,3), (2,4), (3,5), (4,6), (5,7), (6,8), (7,1), (8,2)); 90 | 91 | agent1 = params : gen.gen1; 92 | agent2 = params : gen.gen2; 93 | agent3 = params : gen.gen3; 94 | agent4 = params : gen.gen4; 95 | 96 | network = ( agent1 , 97 | agent2 , 98 | agent3 , 99 | agent4) ~ 100 | circular : gates : stmix; 101 | 102 | process = network; 103 | -------------------------------------------------------------------------------- /lib/bitDSP_conversion.lib: -------------------------------------------------------------------------------- 1 | declare name "bitDSP_conversion"; 2 | declare author "LFSaw (Till Bovermann), Dario Sanfilippo"; 3 | declare copyright "MIT"; 4 | 5 | // bit = library("bitDSP.lib"); // main library 6 | // bit32 = library("bitDSP_int32.lib"); // int32-based library 7 | // bitBus = library("bitDSP_bitBus.lib"); // int32-based library 8 | bitConv = library("bitDSP_conversion.lib"); // conversion between formats library 9 | 10 | // sc = library("scUGens.lib"); // part of https://github.com/tai-studio/faust-sc 11 | // lf = library("taiStudio.lib"); // part of https://github.com/tai-studio/faust-sc 12 | 13 | // import("stdfaust.lib"); 14 | // only import what is necessary 15 | // 16 | // an = library("analyzers.lib"); 17 | ba = library("basics.lib"); 18 | // co = library("compressors.lib"); 19 | de = library("delays.lib"); 20 | // dm = library("demos.lib"); 21 | // dx = library("dx7.lib"); 22 | // en = library("envelopes.lib"); 23 | // fi = library("filters.lib"); 24 | // ho = library("hoa.lib"); 25 | // it = library("interpolators.lib"); 26 | ma = library("maths.lib"); 27 | // mi = library("mi.lib"); 28 | // ef = library("misceffects.lib"); 29 | // os = library("oscillators.lib"); 30 | // no = library("noises.lib"); 31 | // pf = library("phaflangers.lib"); 32 | // pl = library("platform.lib"); 33 | // pm = library("physmodels.lib"); 34 | // rm = library("reducemaps.lib"); 35 | // re = library("reverbs.lib"); 36 | // ro = library("routes.lib"); 37 | // sp = library("spats.lib"); 38 | si = library("signals.lib"); 39 | // so = library("soundfiles.lib"); 40 | // sy = library("synths.lib"); 41 | // ve = library("vaeffects.lib"); 42 | // wa = library("webaudio.lib"); 43 | // sf = library("all.lib"); 44 | // vl = library("version.lib"); 45 | 46 | 47 | // dec2bitBus(N); ----------------------------------------------------------------- 48 | // 49 | // (author: Dario Sanfilipo) 50 | // 51 | // It converts a decimal integer (N) into a Faust list containing the binary 52 | // digits, that is, the binary digits in parallel. 53 | // 54 | // 0 inputs. 55 | // 56 | // M = ceil(ma.log2(N)) outputs: 57 | // y1[n]; 58 | // y2[n]; 59 | // ...; 60 | // yM[n], binary digits representing N. 61 | // 62 | // 1 compile-time arguments: 63 | // N, decimal integer number. 64 | // 65 | dec2bitBus(0) = 0 : !; 66 | dec2bitBus(N) = dec2bitBus(int(N / 2)) , 67 | N % 2; 68 | // ----------------------------------------------------------------------------- 69 | 70 | 71 | //---------------------------------`(bitConv.)bitBus_to_int`--------------------------------------- 72 | // 73 | // (author: Till Bovermann) 74 | // 75 | // turn a stream of parallel binary values into an integer representation by 76 | // left-shifting (<<) the values of the input busses. 77 | // 78 | // assumes values in parallel streams to be either int(0) or int(1) 79 | // 80 | // #### Usage 81 | // 82 | // ``` 83 | // sine = sc.sine(1000, 0); // a float sine wave in [-1, 1] 84 | // process = int(sine * scale) : int32_to_bitBus(32) <: si.bus(32), (bitBus_to_int(32) / scale) with { 85 | // scale = 2147483647; 86 | // }; 87 | // ``` 88 | // 89 | // ``` 90 | // process = (1, 0, 0, 1, 1, 1) : bitBus_to_int(6); 91 | // ``` 92 | bitBus_to_int32 = bitBus_to_int(32); 93 | bitBus_to_int(N) = si.bus(N) : sum(i, N, _ << i); 94 | // bitBusBus2int_custom — alternative implementation 95 | // TODO: fix `left_shift((x0, x1, x2, x3, x4, x5)` for fixed but arbitrary number of channels 96 | // see mail [\[Faudiostream-users\] arbitrary channels to recursive definition?](hook://email/C187E198-7DCB-496D-80CB-39C94EC6F1F6%40lfsaw.de) 97 | // 98 | // bitBusBus2int_custom(N) = si.bus(N) : \(x0, x1, x2, x3, x4, x5).(left_shift((x0, x1, x2, x3, x4, x5))) with { 99 | // left_shift((x, xs)) = left_shift(xs) & ((x > 0) << 1) ; 100 | // left_shift(x) = x > 0; 101 | // }; 102 | // // process = (1, 0, 0, 1, 1, 1) : dsBus2int_custom(6); 103 | 104 | 105 | //---------------------------------`(bitConv.)int32_to_bitBus`--------------------------------------- 106 | // 107 | // (author: Till Bovermann) 108 | // 109 | // turn a 1bit signal into a stream of parallel binary values 110 | // 111 | // assumes values in inout stream to be either 112 | // int(0), int(-1) (low), or 113 | // int(1), (high) 114 | bit_to_int32(0) = 0; // unimodal 115 | bit_to_int32(-1) = 0; // bimodal 116 | // -1 is encoded by all 32 bits 117 | // in high state 118 | bit_to_int32(1) = -1; 119 | 120 | 121 | 122 | //---------------------------------`(bitConv.)int32_to_bitBus`--------------------------------------- 123 | // 124 | // (author: Till Bovermann) 125 | // 126 | // turn an integer signal into a stream of parallel binary values 127 | // left-shifting (<<) the values of the input busses. 128 | // this interprets the input integer as a set of (32) binary values. 129 | // alternative implementation to `dec2bitBus`. 130 | // 131 | // assumes values in parallel streams to be either int(0) or int(1) 132 | // 133 | // #### Usage 134 | // 135 | // ``` 136 | // sine = sc.sine(1000, 0); // a float sine wave in [-1, 1] 137 | // process = int(sine * scale) : int32_to_bitBus(32) <: si.bus(32), (bitBus_to_int(32) / scale) with { 138 | // scale = 2147483647; 139 | // }; 140 | // ``` 141 | int32_to_bitBus(N) = _ <: si.bus(N) : par(i, N, ((1 << i) & _) != 0); 142 | -------------------------------------------------------------------------------- /lib/bitDSP_bitBus.lib: -------------------------------------------------------------------------------- 1 | declare name "bitDSP_binBus"; 2 | declare author "LFSaw (Till Bovermann), Dario Sanfilippo"; 3 | declare copyright "MIT"; 4 | 5 | // bit = library("bitDSP"); // main library 6 | // bit32 = library("bitDSP_int32"); // int32-based library 7 | // bitBus = library("bitDSP_bitBus"); // int32-based library 8 | bitConv = library("bitDSP_conversion.lib"); // conversion between formats library 9 | 10 | // sc = library("scUGens.lib"); // part of https://github.com/tai-studio/faust-sc 11 | // lf = library("taiStudio.lib"); // part of https://github.com/tai-studio/faust-sc 12 | 13 | // import("stdfaust.lib"); 14 | // only import what is necessary 15 | // 16 | // an = library("analyzers.lib"); 17 | ba = library("basics.lib"); 18 | // co = library("compressors.lib"); 19 | de = library("delays.lib"); 20 | // dm = library("demos.lib"); 21 | // dx = library("dx7.lib"); 22 | // en = library("envelopes.lib"); 23 | // fi = library("filters.lib"); 24 | // ho = library("hoa.lib"); 25 | // it = library("interpolators.lib"); 26 | ma = library("maths.lib"); 27 | // mi = library("mi.lib"); 28 | // ef = library("misceffects.lib"); 29 | // os = library("oscillators.lib"); 30 | // no = library("noises.lib"); 31 | // pf = library("phaflangers.lib"); 32 | // pl = library("platform.lib"); 33 | // pm = library("physmodels.lib"); 34 | // rm = library("reducemaps.lib"); 35 | // re = library("reverbs.lib"); 36 | ro = library("routes.lib"); 37 | // sp = library("spats.lib"); 38 | si = library("signals.lib"); 39 | // so = library("soundfiles.lib"); 40 | // sy = library("synths.lib"); 41 | // ve = library("vaeffects.lib"); 42 | // wa = library("webaudio.lib"); 43 | // sf = library("all.lib"); 44 | // vl = library("version.lib"); 45 | 46 | // eca(L, R, I, rate[n]); ------------------------------------------------------ 47 | // 48 | // (author: Dario Sanfilipo) 49 | // 50 | // One-dimension, two-state, elementary cellular automata with circular 51 | // lattice. The function is defined by the length of the lattice, a rule, and 52 | // an initial condition. Additionally, the function has a "rate" parameter 53 | // that determines the interval between iterations. The rule and the initial 54 | // condition are positive INTs that are converted into binary numbers and 55 | // accordingly zero-padded or limited to reach a binary string of 56 | // appropriate length. 57 | // 58 | // Ref: 59 | // Wolfram, S. (1984). Cellular automata as models of complexity. Nature, 60 | // 311(5985), 419-424. 61 | // 62 | // Wolfram, S. (2018). Cellular automata and complexity: collected papers. 63 | // CRC Press. 64 | // 65 | // 1 inputs: 66 | // rate[n], iteration rate. 67 | // 68 | // L outputs: 69 | // y1[n]; 70 | // y2[n]; 71 | // ...; 72 | // yL[n], states of the cells in the lattice. 73 | // 74 | // 3 compile-time arguments: 75 | // L, (positive INT) size of the lattice (number of cells); 76 | // R, (positive INT up to 255) rule applied to the 8 possible cases; 77 | // I, (positive INT) initial condition for the cells. 78 | // 79 | // Sample-and-hold circuits are deployed to have arbitrary iteration 80 | // rates. 81 | eca(L, R, I, rate) = ( si.bus(L) , 82 | init(I) : ro.interleave(L, 2) : par(i, L, +) : 83 | iterate : par(i, L, ba.sAndH(trigger))) 84 | ~ si.bus(L) 85 | with { 86 | // The trigger function needs further testing for extremely 87 | // low iteration rates. 88 | trigger = ba.period(ma.SR / max(ma.EPSILON, rate)) == 0; 89 | // Integer wrap-around function assuming a range between 0 and any 90 | // positive int value M. 91 | wrap(M, N) = int(ma.frac(N / M) * M); 92 | // "Wolfram Number" – an int between 0 and 255 representing 93 | // all 256 possible outcomes for the eight cases (see below). 94 | // Eight total cases and two possible outcomes for each case, 95 | // hence 2^8 rules. Rule 30 and 110 are well-known. 96 | w_num = zeropad_up(int(8 - ceil(ma.log2(R1))), bitConv.dec2bitBus(R1)) 97 | with { 98 | R1 = min(255, R); 99 | }; 100 | // Initial value for the cells, also expressed as an int. If 101 | // the binary value of the init is larger than the lattice, 102 | // the value is clipped. If smaller, 0s are added at the top 103 | // until the binary string matches the lattice length. 104 | init(N) = zeropad_up(int(L - (floor(ma.log2(N1)) + 1)), 105 | bitConv.dec2bitBus(N1)) : par(i, L, _ <: _ - mem) 106 | with { 107 | N1 = min(N, 2 ^ L - 1); 108 | }; 109 | // Rule application through nested IFs. The rule changes the 110 | // state of a cell according to the state of its neighbouring 111 | // cells. Note that this is a circular latice, hence the 112 | // state of the first cell is determined by the second one and 113 | // the last one. 114 | rule(x1, x2, x3) = 115 | ba.if( c1, w_num : route(8, 1, 1, 1), 116 | ba.if( c2, w_num : route(8, 1, 2, 1), 117 | ba.if( c3, w_num : route(8, 1, 3, 1), 118 | ba.if( c4, w_num : route(8, 1, 4, 1), 119 | ba.if( c5, w_num : route(8, 1, 5, 1), 120 | ba.if( c6, w_num : route(8, 1, 6, 1), 121 | ba.if( c7, w_num : route(8, 1, 7, 1), 122 | w_num : route(8, 1, 8, 1)))))))) 123 | // Two states for three cells, hence 2^3 conditions. 124 | // Note that the last one is implicit and not used in 125 | // the IFs above, although it is informative having it 126 | // here. 127 | with { 128 | c1 = (x1 == 1) & (x2 == 1) & (x3 == 1); 129 | c2 = (x1 == 1) & (x2 == 1) & (x3 == 0); 130 | c3 = (x1 == 1) & (x2 == 0) & (x3 == 1); 131 | c4 = (x1 == 1) & (x2 == 0) & (x3 == 0); 132 | c5 = (x1 == 0) & (x2 == 1) & (x3 == 1); 133 | c6 = (x1 == 0) & (x2 == 1) & (x3 == 0); 134 | c7 = (x1 == 0) & (x2 == 0) & (x3 == 1); 135 | c8 = (x1 == 0) & (x2 == 0) & (x3 == 0); 136 | }; 137 | iterate = si.bus(L) <: 138 | par(i, L, route(L, 3, wrap(L, i - 1) + 1, 1, 139 | i + 1, 2, 140 | wrap(L, i + 1) + 1, 3) : int(rule)); 141 | }; 142 | // ----------------------------------------------------------------------------- 143 | 144 | // zeropad_up(N, list); -------------------------------------------------------- 145 | // 146 | // (author: Dario Sanfilipo) 147 | // 148 | // This function adds N zeros at the beginning of a list. 149 | // 150 | // 0 inputs. 151 | // 152 | // N+ba.count(list) outputs. 153 | // 154 | // 1 compile-time arguments: 155 | // N, number of zeros to be added. 156 | // 157 | zeropad_up(0, x) = x; 158 | zeropad_up(N, x) = par(i, N, 0) , x; 159 | // ----------------------------------------------------------------------------- 160 | -------------------------------------------------------------------------------- /lib/bitDSP_gen.lib: -------------------------------------------------------------------------------- 1 | import("stdfaust.lib"); 2 | bit = library("bitDSP.lib"); 3 | 4 | // c1, c2 in range [0..1] 5 | 6 | //////////////////////////// bfb //////////////////////// 7 | // author: Till Bovermann 8 | // c1, c2 in range [0..1] 9 | // c1 = hslider("c1", 0, 0, 1, 0.0001); 10 | // c2 = hslider("c2", 0, 0, 1, 0.0001); 11 | // process = bfb(c1, c2); 12 | 13 | 14 | bfb(c1, c2) = p(c1, c2 * 10) with { 15 | // mod(a, 0) = 0; 16 | mod(a, b) = select2(b > 0, 0, ba.if(a > 0, a % b, a % b + b)); 17 | 18 | bool_osc1_mod(d1, d2) = node1 letrec { 19 | 'node1 = not(node1 xor node2 & node1) @ abs(min(ma.SR,mod(d1, ma.SR))); 20 | 'node2 = not(node2 xor node1 xor node2) @ abs(min(ma.SR,mod(d2, ma.SR))); 21 | } with { 22 | not(x) = rint(1 - x); 23 | }; 24 | bool_osc2_mod(d1, d2) = node1 letrec { 25 | 'node1 = not(node1 & node2) @ abs(min(ma.SR,mod(d1, ma.SR))); 26 | 'node2 = not(node1 & node2) @ abs(min(ma.SR,mod(d2, ma.SR))); 27 | } with { 28 | not(x) = rint(1 - x); 29 | }; 30 | 31 | // sc-like leakdc 32 | leakdc(coef, x) = y letrec { 33 | 'y = x - x' + coef * y; 34 | }; 35 | selectx(which, x, y) = (which * x) + ((1-which) * y); 36 | 37 | 38 | leak = 0.00003; 39 | 40 | d11 = (1 - d21bias) * 0.0009; 41 | d12 = (1 - d22bias) * 0.001; 42 | d21 = (1 - d11bias) * 0.001; 43 | d22 = (1 - d12bias) * 0.0011; 44 | d11bias = d21bias * 0.99; 45 | d12bias = d22bias * 0.9499; 46 | d22bias = 27; 47 | d21bias = 164; 48 | 49 | p(coef_in, xfb) = oscfb(coef_in, xfb, d11bias, d11, d12bias, d12, d21bias, d21, d22bias, d22) : par(i, 2, (_ > 0)) with { 50 | leakcoef = 1 - ((1-coef_in) * 0.0001); 51 | oscfb(leakcoef, xfb, d11bias, d11, d12bias, d12, d21bias, d21, d22bias, d22) = (loop ~ (_, _)) with { 52 | loop(fb1, fb2) = 53 | loop1( 54 | selectx(xfb * 1.1, fb1, fb2), 55 | leakcoef, 56 | d11bias, d11, 57 | d12bias, d12 58 | ), 59 | loop2( 60 | selectx(1 - xfb, fb2, fb1), 61 | leakcoef, 62 | d21bias, d21, 63 | d22bias, d22 64 | ); 65 | loop1(fb, coef, d1off, d1, d2off, d2) = 66 | bool_osc1_mod( 67 | max(0, d1off + (fb * 20 * d1)), 68 | max(0, d2off + (fb * 1500 * d2)) 69 | ) 70 | : leakdc(coef); 71 | loop2(fb, coef, d1off, d1, d2off, d2) = 72 | bool_osc2_mod( 73 | max(0, d1off + (fb * 1000 * d1)), 74 | max(0, d2off + (fb * 500 * d2)) 75 | ) 76 | : leakdc(coef); 77 | }; 78 | }; 79 | }; 80 | 81 | 82 | //////////////////////////// higks //////////////////////// 83 | // author: Till Bovermann 84 | // c1 = hslider("d_bias1[scale:exp]", 0.0001, 0.0001, 1, 0.00001); 85 | // c2 = hslider("d_bias2[scale:exp]", 0.0001, 0.0001, 1, 0.00001); 86 | // process = higks(c1, c2); 87 | 88 | higks(b1, b2) = 89 | oscfb1(leakcoef, bias1, bias2, mod1, mod2), 90 | oscfb2(leakcoef, bias1, bias2, mod1, mod2) 91 | : onebit 92 | : si.bus(2) 93 | with { 94 | bias1 = b1 * 0.9999 + 0.0001; 95 | bias2 = b2 * 0.9999 + 0.0001; 96 | // amp = hslider("m_amp", 0, 0, 4, 0.001) : si.smoo; 97 | coef_in = 0.492; 98 | leakcoef = 1 - (coef_in * 0.001); 99 | mod1 = 0.032; 100 | mod2 = 0.014; 101 | onebit = par(i, 2, (_ > 0)); 102 | 103 | bool_osc1_mod(del1, del2) = node1 letrec { 104 | 'node1 = not(node1 xor node2 & node1) @ min(ma.SR,(del1 % ma.SR)); 105 | 'node2 = not(node2 xor node1 xor node2) @ min(ma.SR,(del2 % ma.SR)); 106 | } with { 107 | not(x) = 1 - x; 108 | }; 109 | bool_osc2_mod(del1, del2) = node1 letrec { 110 | 'node1 = not(node1 & node2) @ min(ma.SR,(del1 % ma.SR)); 111 | 'node2 = not(node1 & node2) @ min(ma.SR,(del2 % ma.SR)); 112 | } with { 113 | not(x) = rint(1 - x); 114 | }; 115 | oscfb1(leakcoef, bias1, bias2, mod1, mod2) = loop ~ _ with { 116 | loop(fb) = bool_osc1_mod( 117 | (fb : map(bias1, mod2)), 118 | (fb : map(bias2, mod1)) 119 | ) : leakdc(leakcoef); 120 | }; 121 | oscfb2(leakcoef, bias1, bias2, mod1, mod2) = loop ~ _ with { 122 | loop(fb) = bool_osc2_mod( 123 | (fb : map(bias1, mod1)), 124 | (fb : map(bias2, mod2)) 125 | ) : leakdc(leakcoef); 126 | }; 127 | map(bias, scale, in) = max(0, (bias * biasfac) + (scale * in * modfac)) with { 128 | biasfac = 15000; 129 | modfac = 15000; 130 | }; 131 | // sc-like leakdc 132 | leakdc(coef, x) = y letrec { 133 | 'y = x - x' + coef * y; 134 | }; 135 | 136 | }; 137 | 138 | 139 | ////////////////// lowPressure ////////////// 140 | // declare author "Till Bovermann"; 141 | 142 | // c1 = hslider("c1",0,0,1,0.001); 143 | // c2 = hslider("c2",0,0,1,0.001); 144 | // process = lowPressure(c1, c2); 145 | 146 | lowPressure(c1, c2) = 147 | bool_osc1(dt1, dt2), 148 | bool_osc2(dt2, dt1) 149 | : swap(bool_osc3(dt1, dt1)) : si.bus(2) with { 150 | dt1 = int(0.671 * (c1 + 0.1 * 0.9) * ma.SR); 151 | dt2 = int(0.142 * 0.5 * c2 * ma.SR); 152 | 153 | mod(a, b) = select2(b > 0, 0, ba.if(a > 0, a % b, a % b + b)); 154 | 155 | not(x) = 1 - x; 156 | pulser(d1, d2) = os.lf_pulsetrain(d2 * d1 + 0.01, 0.5) > 0; 157 | bool_osc1(del1, del2) = node1 letrec { 158 | 'node1 = not(node1 xor node2 & node1) @ max(0, min(ma.SR,(del1 % ma.SR))); 159 | 'node2 = not(node2 xor node1 xor node2) @ max(0, min(ma.SR,(del2 % ma.SR))); 160 | }; 161 | bool_osc2(del1, del2) = node1 letrec { 162 | 'node1 = not(node1 xor node2 | node1 | pulser(node1, 1)) @ max(0, min(ma.SR,(del1 % ma.SR))); 163 | 'node2 = not(node2 | pulser(del1, node1) xor node1 xor node2) @ max(0, min(ma.SR,(del2 % ma.SR))); 164 | }; 165 | bool_osc3(del1, del2) = node2 letrec { 166 | 'node1 = not(node1 xor node2 | node1) @ max(0, min(ma.SR,(del1 % ma.SR))); 167 | 'node2 = not(node2 | node1 xor node2) @ max(0, min(ma.SR,(del2 % ma.SR))); 168 | }; 169 | swap(a, x, y) = select2(a, x, y), select2(a, y, x); 170 | }; 171 | 172 | ////////////////// trck ////////////// 173 | // declare author "Till Bovermann"; 174 | 175 | // c1 = hslider("c1",0,0,1,0.001); 176 | // c2 = hslider("c2",0,0,1,0.001); 177 | // process = trck(c1, c2); 178 | 179 | trck(c1,c2) = y2 | y3 | y1, y5 | y4 letrec { 180 | 'y1 = (impulse(N + (100 * y2))>0) | (y2 - y1@(int(c2 * 17))) >0; 181 | 'y2 = not(y1 & y3@(int(c2 * 23))); 182 | 'y5 = not(y4 & y5); 183 | 'y3 = (impulse(N + (100 * y4@124)) > 0)| (y2 - y1@(1 + int(c1 * 27))) >0; 184 | 'y4 = (impulse(N - (100 * (y5 + y1@10))) > 0) | (y1 - y5@(3 + int(c1 * 17))) > 0; 185 | } with { 186 | N = 128 * 2; 187 | not(x) = (1 - (x>0)); 188 | // dirac = 1 - 1'; 189 | impulse(freq) = os.lf_imptrain(freq); 190 | }; 191 | 192 | 193 | 194 | // ============================================================================= 195 | // Dario's section 196 | // ============================================================================= 197 | 198 | // ---------- GEN1 ------------------------------------------------------------- 199 | // 200 | gen1(cf1_, cf2_) = y1 , y2 201 | letrec { 202 | 'y1 = bit.lp1bit_clip_r(0, -L, L, 1, cf1, y2); 203 | 'y2 = bit.hp1bit_clip_r(0, -L, L, 1, cf2, y1); 204 | } 205 | with { 206 | cf1 = ma.frac(cf1_); 207 | cf2 = ma.frac(cf2_); 208 | L = 4; 209 | }; 210 | // ----------------------------------------------------------------------------- 211 | 212 | // ---------- GEN2 ------------------------------------------------------------- 213 | // 214 | gen2(G_, fb_) = y1 , y2 215 | letrec { 216 | 'y1 = bit.orx(y2, bit.int1bit_clip_r(reset(y1), -L, L, G, y1 * fb)); 217 | 'y2 = bit.orx(y1, bit.int1bit_clip_r(reset(y2), -L, L, G, y2 * -fb)); 218 | } 219 | with { 220 | G = ma.frac(G_) * 1024; 221 | fb = ma.frac(fb_); 222 | L = 1024; 223 | reset(x) = ba.if(cond, 1, 0) 224 | with { 225 | cond = acc >= ma.SR; 226 | acc = fi.pole(detect, detect); 227 | detect = x - x' == 0; 228 | }; 229 | }; 230 | // ----------------------------------------------------------------------------- 231 | 232 | // ---------- GEN3 ------------------------------------------------------------- 233 | // 234 | gen3(fb1_, fb2_) = y1 , y2 235 | letrec { 236 | 'y1 = bit.or(bit.ddsm1_clip_r(0, -L, L, 1, bit.and(y2, y1) * fb1), 237 | bit.ddsm1_clip_r(0, -L, L, 1, y1 * fb1)); 238 | 'y2 = bit.orx(bit.ddsm1_clip_r(0, -L, L, 1, bit.and(y2, y1) * fb2), 239 | bit.ddsm1_clip_r(0, -L, L, 1, y2 * fb2)); 240 | } 241 | with { 242 | fb1 = fmod(fb1_ * 2 -1, 1); 243 | fb2 = fmod(fb2_ * 2 -1, 1); 244 | L = 64; 245 | }; 246 | // ----------------------------------------------------------------------------- 247 | 248 | // ---------- GEN4 ------------------------------------------------------------- 249 | // 250 | gen4(fb_, pattern_) = y1 , y2 251 | letrec { 252 | 'y1 = nl1(plus(bit.ddsm1_clip_r(0, -L, L, 1, nl2(plus(nl1(y2), 253 | nl2(y1))) * fb), bit.ddsm1_clip_r(0, -L, L, 1, nl1(y1) * fb))); 254 | 'y2 = nl3(plus(bit.ddsm1_clip_r(0, -L, L, 1, nl4(plus(nl3(y2), 255 | nl4(y1))) * -fb), bit.ddsm1_clip_r(0, -L, L, 1, nl3(y2) * -fb))); 256 | } 257 | with { 258 | fb = ma.tanh(3 * (fb_ * 2 - 1)); 259 | pattern = ma.frac(pattern_); 260 | L = 2; 261 | S = 3; 262 | N1 = int(pattern * S) % S; 263 | N2 = (N1 + 1) % S; 264 | N3 = (N2 + 1) % S; 265 | N4 = (N3 + 1) % S; 266 | nl1(x) = bit.pattern_bitflip_sig(S, x, N1); 267 | nl2(x) = bit.pattern_bitflip_sig(S, x, N2); 268 | nl3(x) = bit.pattern_bitflip_sig(S, x, N3); 269 | nl4(x) = bit.pattern_bitflip_sig(S, x, N4); 270 | plus(x1, x2) = bit.bitstream_adder(x1, x2); 271 | }; 272 | // ----------------------------------------------------------------------------- 273 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # bitDSP in faust 2 | *[Till Bovermann](http://tai-studio.org) & [Dario Sanfilippo](https://www.dariosanfilippo.com/) for the [rottingsounds project](http://rottingsounds.org)* 3 | 4 | BitDSP is a set of [faust](http://faust.grame.fr/) library functions aimed to help explore and research artistic possibilities of bit-based algorithms. 5 | BitDSP offers three data formats to handle 1-bit data streams: 6 | 7 | 1. `integer`-based 8 | 2. `bitBus` 9 | 3. `int32` 10 | 11 | BitDSP currently includes implementations of bit-based functions ranging from simple bit operations over classic delta-sigma modulations to more experimental approaches like cellular automata, recursive Boolean networks, and linear feedback shift registers. 12 | 13 | A detailed overview of the functionality is in the [paper](https://ifc20.sciencesconf.org/332745/document) "Creative use of bit-stream DSP in faust" presented at [IFC 2020](https://ifc20.sciencesconf.org/). 14 | 15 | 16 | ## data-types 17 | 18 | ### integer-based 19 | 20 | A straight-forward implementation in which each 1-bit sample is represented as an integer value that is either 0, 1. 21 | 22 | This representation allows to implement bit-based operators utilising standard operators. 23 | 24 | For real-time applications, sample rates are, however, limited to the maximum sample-rate supported by the audio interface. 25 | 26 | Another limiting factor is that each 1-bit value is represented by (typically) 32 bits, hence computational and memory allocation is far bigger than necessary. 27 | 28 | ### `bitBus` 29 | 30 | (parallel processing of parallel bit-streams) 31 | 32 | The bit-stream is represented by an N-dimensional signal bus of N consecutive samples of the bit-stream in N parallel streams. 33 | 34 | This results in an oversampling relative to the sample-rate by a factor of N. 35 | 36 | This approach requires unfolding of feedback paths over the N signal buses, which means that standard implementation of the libraries utilising feedback operators cannot be integrated. Instead, specific versions need to be written. 37 | 38 | ![unfolding figure](_assets/bitDSP_unfolding.jpg) 39 | 40 | 41 | 42 | ### `int32` 43 | 44 | The bit-stream is encoded in a faust-native integer signal as a sequence of bits that need to be processed in parallel. For now, an integer in faust typically translates into a 32bit signed integer. Implementations are therefore equivalent to the bitBus bversion with `N=32`. 45 | The resulting upsampling factor is therefore `N=32`. 46 | 47 | Straight-forward operators for the int32 representation are e.g. `bitAnd`, `bitOr` and `bitNot` which is strangely not implemented natively in faust. 48 | 49 | Other operators are e.g. left-shift or right-shift for which we also had to rely on external functions because right-shift operators are unfortunately confusingly defined for signed integers in C-like languages. 50 | 51 | 52 | ## Examples 53 | 54 | Examples are available in the [examples folder](https://github.com/rottingsounds/bitDSP-faust/tree/master/examples). Each example dsp file has examples on how to compile the dsp file into a running application. 55 | 56 | There is also a dedicated SuperCollider examples folder. 57 | 58 | 59 | ## Acknowledgements 60 | 61 | This research has been funded through [RottingSounds](http://rottingsounds.org) (project AR 445-G24) by the Austrian Science Fund (FWF). 62 | 63 | 64 | Subsequent is a list of currently implemented functions (last updated on 2020-12-01). 65 | 66 | - [Implemented functionality](#implemented-functionality) 67 | * [integer-based](#integer-based-1) 68 | + [`bool_osc0`](#-bool-osc0-) 69 | + [`bool_osc1`](#-bool-osc1-) 70 | + [`bool_osc2`](#-bool-osc2-) 71 | + [`cic`](#-cic-) 72 | + [`delta`](#-delta-) 73 | + [`dsm1`](#-dsm1-) 74 | + [`dsm2`](#-dsm2-) 75 | + [`full_adder`](#-full-adder-) 76 | + [`bitstream_adder`](#-bitstream-adder-) 77 | + [`bitrot`](#-bitrot-) 78 | * [`bitBus`](#-bitbus-n---1) 79 | + [`eca`](#-eca-) 80 | + [`zeropad_up`](#-zeropad-up-) 81 | * [`int32`](#-int32--1) 82 | + [`bitNot`](#-bitnot-) 83 | + [`left_shift`](#-left-shift-) 84 | + [`right_shift`](#-right-shift-) 85 | + [`maskedNot`](#-maskednot-) 86 | + [`maskedAnd`](#-maskedand-) 87 | + [`maskedOr`](#-maskedor-) 88 | + [`maskedXor`](#-maskedxor-) 89 | + [`applyMask`](#-applymask-) 90 | + [`bit_mask`](#-bit-mask-) 91 | + [`delay32`](#-delay32-) 92 | + [`delay`](#-delay-) 93 | + [`int_min`, `int_max`,](#-int-min----int-max--) 94 | + [`parity`](#-parity-) 95 | + [`div`](#-div-) 96 | + [`lfsr` and `lfsr32`](#-lfsr--and--lfsr32-) 97 | + [`bitDAC` and `bitDAC_i`](#-bitdac--and--bitdac-i-) 98 | + [`dsm1` and `dsm1_32`](#-dsm1--and--dsm1-32-) 99 | * [conversion](#conversion) 100 | + [`dec2bitBus`](#-dec2bitbus-) 101 | + [`bitBus_to_int`](#-bitbus-to-int-) 102 | + [`int32_to_bitBus`](#-int32-to-bitbus-) 103 | + [`int32_to_bitBus`](#-int32-to-bitbus--1) 104 | 105 | 106 | 107 | ## Implemented functionality 108 | 109 | ### integer-based 110 | 111 | All implementations are located in [bitDSP.lib](https://github.com/rottingsounds/bitDSP-faust/blob/master/lib/bitDSP.lib). There you can also find detailed descriptions of their functionality. 112 | 113 | To use them in your code, add 114 | 115 | ``` 116 | bit = library("bitDSP.lib"); 117 | ``` 118 | 119 | to your `.dsp`-file. 120 | 121 | #### `bool_osc0` 122 | 123 | Basic Boolean oscillator with four cross-coupled nodes, mainly for chaotic oscillations including limit cycles and strange attractors. 124 | 125 | #### `bool_osc1` 126 | 127 | Basic Boolean oscillator with two cross-coupled nodes, mainly for chaotic oscillations including limit cycles and strange attractors. 128 | 129 | #### `bool_osc2` 130 | 131 | Basic Boolean oscillator with two cross-coupled nodes, mainly for chaotic oscillations including limit cycles and strange attractors. 132 | 133 | #### `cic` 134 | 135 | Comb-integrator circuit lowpass filter based on Eric Lyon's [article](https://www.dsprelated.com/showarticle/1337.php). 136 | 137 | #### `delta` 138 | 139 | First derivative using linear interpolation delay lines, hence allowing fractional differentiation periods. 140 | 141 | #### `dsm1` 142 | 143 | First-order digital delta-sigma modulator. 144 | 145 | ![dsm1_block](_assets/dsm1_block.jpg) 146 | 147 | 148 | #### `dsm2` 149 | 150 | Second-order digital delta-sigma modulator. 151 | 152 | ![dsm2-drawn](_assets/dsm2-drawn.jpg) 153 | 154 | 155 | #### `full_adder` 156 | 157 | Adder for binary values. It adds two operands as well as a carrier input. It outputs the sum as well as the carrier output. 158 | 159 | #### `bitstream_adder` 160 | 161 | Adder for delta-sigma-modulated streams. 162 | 163 | #### `bitrot` 164 | 165 | Under a specified likelihood (`noise`, `chance`) and depending on `type`, either 166 | 167 | + `type == -1` -- set a bit's value to low 168 | + `type == 0` -- flip bit 169 | + `type == 1` -- set a bit's value to high 170 | 171 | 172 | 173 | ![bitRot](_assets/bitRot.jpg) 174 | 175 | 176 | ### `bitBus` 177 | 178 | All implementations are located in [bitDSP_bitBus.lib](https://github.com/rottingsounds/bitDSP-faust/blob/master/lib/bitDSP_bitBus.lib). There you can also find detailed descriptions of their functionality. 179 | 180 | To use them in your code, add 181 | 182 | ``` 183 | bitBus = library("bitDSP_bitBus"); 184 | ``` 185 | 186 | to your `.dsp`-file. 187 | 188 | 189 | #### `eca` 190 | 191 | One-dimension, two-state, elementary cellular automata with circular lattice. The function is defined by the length of the lattice, a rule, and an initial condition. Additionally, the function has a "rate" parameter that determines the interval between iterations. The rule and the initial condition are positive INTs that are converted into binary numbers and accordingly zero-padded or limited to reach a binary string of appropriate length. 192 | 193 | #### `zeropad_up` 194 | 195 | Add `N` zeros at the beginning of a list. 196 | 197 | 198 | ### `int32` 199 | 200 | All implementations are located in [bitDSP_int32.lib](https://github.com/rottingsounds/bitDSP-faust/blob/master/lib/bitDSP_int32.lib). There you can also find detailed descriptions of their functionality. 201 | 202 | To use them in your code, add 203 | 204 | ``` 205 | bit32 = library("bitDSP_int32"); 206 | ``` 207 | 208 | to your `.dsp`-file. 209 | 210 | #### `bitNot` 211 | 212 | bitwise Not 213 | 214 | *Note: relies on foreign functions (c-based platforms only).* 215 | 216 | #### `left_shift` 217 | 218 | Unsigned left shift operator. 219 | 220 | *Note: relies on foreign functions (c-based platforms only).* 221 | 222 | 223 | #### `right_shift` 224 | 225 | Unsigned right shift operator. 226 | 227 | *Note: relies on foreign functions (c-based platforms only).* 228 | 229 | #### `maskedNot` 230 | 231 | Invert selected bits of an integer. 232 | 233 | *Note: relies on foreign functions (c-based platforms only).* 234 | 235 | 236 | #### `maskedAnd` 237 | 238 | Bit-wise AND of selected bits of two integers. 239 | Remaining bits are kept from first parameter. 240 | 241 | #### `maskedOr` 242 | 243 | Bit-wise OR of selected bits of two integers. 244 | Remaining bits are kept from first parameter. 245 | 246 | #### `maskedXor` 247 | 248 | Bit-wise XOR of selected bits of two integers. 249 | Remaining bits are kept from first parameter. 250 | 251 | #### `applyMask` 252 | 253 | Apply result only to selected bits. 254 | 255 | #### `bit_mask` 256 | 257 | Create bit mask with indices at list values `== 1`. 258 | 259 | *Note: relies on foreign functions (c-based platforms only)* 260 | 261 | #### `delay32` 262 | 263 | Single-bit delay on an integer bitstream. maximum of 32bit delays possible. 264 | 265 | *Note: relies on foreign functions (c-based platforms only).* 266 | 267 | #### `delay` 268 | 269 | Single-bit delay on integer bitstream. 270 | 271 | 272 | 273 | #### `int_min`, `int_max`, 274 | 275 | Minimum resp. Maximum value of integer datatype. 276 | 277 | 278 | #### `parity` 279 | 280 | Compute parity of a 32bit integer (assuming it to be unsigned) 281 | 282 | #### `div` 283 | 284 | integer division. 285 | 286 | *Note: relies on foreign functions (c-based platforms only).* 287 | 288 | #### `lfsr` and `lfsr32` 289 | 290 | Compute LFSR on a 32bit resp. `N`-bit integer bitset (assuming it to be unsigned). 291 | Resets on changed input state. 292 | See https://en.wikipedia.org/wiki/Linear-feedback_shift_register for details on LFSRs. 293 | 294 | *Note: relies on foreign functions (c-based platforms only).* 295 | 296 | ![](_assets/ShiftRegister-LFSR.jpg) 297 | 298 | 299 | #### `bitDAC` and `bitDAC_i` 300 | 301 | Select bits of an integer to be interpreted as PCM values. 302 | Range is `[0, 1, .. (2^size)[` resp. `[0.f .. 1]`. 303 | 304 | *Note: relies on foreign functions (c-based platforms only).* 305 | 306 | 307 | ![bitDAC](_assets/bitDAC.jpg) 308 | 309 | 310 | 311 | #### `dsm1` and `dsm1_32` 312 | 313 | Delta-sigma converter for a float-encoded multibit-stream. 314 | It turns the incoming signal into a binary stream packed into chuncks of a 32. 315 | 316 | ![dsm1_bitBus](_assets/dsm1_bitBus.jpg) 317 | 318 | ### conversion 319 | 320 | All implementations are located in [bitDSP_conversion.lib](https://github.com/rottingsounds/bitDSP-faust/blob/master/lib/bitDSP_conversion.lib). There you can also find detailed descriptions of their functionality. 321 | 322 | To use them in your code, add 323 | 324 | ``` 325 | bitConv = library("bitDSP_conversion"); 326 | ``` 327 | 328 | to your `.dsp`-file. 329 | 330 | #### `dec2bitBus` 331 | 332 | Converts a decimal integer (N) into a Faust list containing the binary digits, that is, the binary digits in parallel. 333 | 334 | 335 | #### `bitBus_to_int` 336 | 337 | turn a stream of parallel binary values into an integer representation by left-shifting (`<<`) the values of the input busses. 338 | 339 | 340 | #### `int32_to_bitBus` 341 | 342 | Turn a 1bit signal into a stream of parallel binary values 343 | 344 | #### `int32_to_bitBus` 345 | 346 | turn an integer signal into a stream of parallel binary values 347 | left-shifting (`<<`) the values of the input busses. 348 | this interprets the input integer as a set of (32) binary values. 349 | alternative implementation to `dec2bitBus`. 350 | -------------------------------------------------------------------------------- /test/rbn.dsp: -------------------------------------------------------------------------------- 1 | // ============================================================================= 2 | // Preliminary tests for random Boolean networks. 3 | // reference paper: https://arxiv.org/pdf/0706.3351v2.pdf 4 | // quick introduction: http://www.complexityexplorer.org/system/explore/models/writeup_files/000/000/040/original/random-boolean.pdf 5 | // ============================================================================= 6 | 7 | declare author "Dario Sanfilippo"; 8 | declare copyright "Copyright (C) 2020 Dario Sanfilippo 9 | "; 10 | declare lcg_par license "GPL v3 license"; 11 | 12 | import("stdfaust.lib"); 13 | 14 | // AUXILIARY FUNCTIONS 15 | 16 | //------------------------------------------------------------------------------ 17 | // Linear congruential generator for streams of integer values based on 18 | // the equation: y[n] = (A * y[n - 1] + C) % M. 19 | // See https://en.wikipedia.org/wiki/Linear_congruential_generator. 20 | // 21 | // For a period-(M-1) LCG, with C != 0, we must satisfy the following conditions: 22 | // 23 | // 1: M and C are relatively prime, 24 | // 2: A-1 is divisible by all prime factors of M, 25 | // 3: A-1 is divisible by 4 if M is divisible by 4. 26 | // 27 | // This way, full-period cycles are guaranteed with any seeds != 0. 28 | // 29 | // For example, we can use lcg(14, 15, 5, S) to select the update functions 30 | // with uniform probability. 31 | // 32 | // For power-of-two Ms, C should be coprime to M and A should 1+4K, where K 33 | // is an int, to have a full-cycle LCG. 34 | // 35 | // #### Usage 36 | // 37 | // ```` 38 | // lcg(M, A, C, S) : _ 39 | // ```` 40 | // 41 | // Where: 42 | // 43 | // * M is the divisor in the modulo operation. 44 | // * A is the multiplier. 45 | // * C is the offset. 46 | // * S is the seed. 47 | // 48 | // #### Reference: 49 | // 50 | // L’ecuyer, P. (1999). Tables of linear congruential generators of different 51 | // sizes and good lattice structure. Mathematics of Computation, 68(225), 52 | // 249-260. 53 | // 54 | // Steele, G., & Vigna, S. (2020). Computationally easy, spectrally good 55 | // multipliers for congruential pseudorandom number generators. arXiv 56 | // preprint arXiv:2001.05304. 57 | // 58 | lcg(M, A, C, S) = ((+ (S - S') * A + C) % M) ~ _; 59 | //------------------------------------------------------------------------------ 60 | 61 | // ----------------------------------------------------------------------------- 62 | // Linear congruential list generator 63 | // 64 | lcg_par(1, M, A, C, S) = (A * S + C) % M; 65 | lcg_par(N, M, A, C, S) = (A * S + C) % M , 66 | lcg_par(N - 1, M, A, C, (A * S + C) % M); 67 | // ----------------------------------------------------------------------------- 68 | 69 | // ----------------------------------------------------------------------------- 70 | // Negation for single-digit binary values. 71 | // 72 | not(N) = rint(1 - N); 73 | // ----------------------------------------------------------------------------- 74 | 75 | // ----------------------------------------------------------------------------- 76 | // UPDATE FUNCTIONS 77 | // The input cases for K = 2 (i.e., two-input genes) are: 00 - 01 - 10 - 11. 78 | // Four input cases and binary updates, hence 2^4 update functions. 79 | // The update functions below determine the next state of each gene depending 80 | // on the inputs. 81 | // The 'frozen' update functions 1111 and 0000 are not considered. 82 | // 83 | uf(1) = &; // 0001 84 | uf(2) = si.bus(2) <: uf(3) & uf(6); // 0010 85 | uf(3) = _ , 86 | (_ : !); // 0011 87 | uf(4) = si.bus(2) <: uf(6) & uf(12); // 0100 88 | uf(5) = (_ : !) , 89 | _; // 0101 90 | uf(6) = xor; // 0110 91 | uf(7) = |; // 0111 92 | uf(8) = not(|); // 1000 93 | uf(9) = not(xor); // 1001 94 | uf(10) = not(uf(5)); // 1010 95 | uf(12) = not(uf(3)); // 1100 96 | uf(11) = not(uf(4)); // 1011 97 | uf(13) = not(uf(2)); // 1101 98 | uf(14) = not(&); // 1110 99 | // ----------------------------------------------------------------------------- 100 | 101 | // ----------------------------------------------------------------------------- 102 | // This function creates a list with the digits of an integer number. 103 | // 104 | digits_par(0) = 0 : !; 105 | digits_par(N) = digits_par(int(N / 10)) , 106 | N % 10; 107 | // ----------------------------------------------------------------------------- 108 | 109 | // ----------------------------------------------------------------------------- 110 | // This function converts from binary to decimal. 111 | // 112 | bin2dec(0) = 0; 113 | bin2dec(B) = digits_par(B) : par(i, elem, *(2 ^ (elem - (i + 1)))) :> _ 114 | with { 115 | elem = outputs(digits_par(B)); 116 | }; 117 | // ----------------------------------------------------------------------------- 118 | 119 | // ----------------------------------------------------------------------------- 120 | // Genes array generation through randomly chosen update functions. 121 | // This function takes an int, N, indicating the array size, and a seed, S, for 122 | // an LCG function that generates N seeds for N LCG functions. 123 | // The gene selection has a uniform probability distribution p = 1/14. 124 | // Roughly, the given seed should be a positive int between 1 and 2^16. 125 | // 126 | genes(N, S) = 127 | par(i, N, uf(lcg_par(1, 14, 15, 5, ba.take(i + 1, seeds) + 1) + 1)) 128 | with { 129 | seeds = lcg_par(N, 65521, 17364, 0, S); 130 | }; 131 | // ----------------------------------------------------------------------------- 132 | 133 | // ----------------------------------------------------------------------------- 134 | // This function generates uniformely distributed (or almost) positive random 135 | // ints between 0 and M-1. The function also takes a seed, S. 136 | // 137 | rand_int(M, S) = abs(random) % M 138 | with { 139 | mask = 4294967295; // 2^32-1 140 | random = (+(S) : *(1103515245) & mask) 141 | ~ _; // "linear congruential" 142 | }; 143 | // ----------------------------------------------------------------------------- 144 | 145 | // ----------------------------------------------------------------------------- 146 | // This recursive function generates a gene with arbitrary K (inputs) based on 147 | // a seed between 1 and 2^16, roughly. The genes are generated as homogeneous 148 | // combinations of the 14 K=2 update functions defined above. 149 | // 150 | gene(2, S) = uf(ba.take(1, org) + 1) 151 | with { 152 | org = lcg_par(1, 14, 15, 5, S); 153 | }; 154 | gene(K, S) = 155 | uf(ba.take(K - 1, org) + 1, gene(K - 1, S)) 156 | with { 157 | org = lcg_par(K - 1, 14, 15, 5, S); 158 | }; 159 | // ----------------------------------------------------------------------------- 160 | 161 | // ----------------------------------------------------------------------------- 162 | // This function generates a genes array of size N with arbitrary K based on 163 | // a seed between 1 and 2^16, roughly. 164 | // 165 | genes2(N, K, S) = par(i, N, gene(K, ba.take(i + 1, seeds) + 1)) 166 | with { 167 | seeds = lcg_par(N, 65521, 17364, 0, S); 168 | }; 169 | // ----------------------------------------------------------------------------- 170 | 171 | // ----------------------------------------------------------------------------- 172 | // This function creates a list of N elements with random ints between 173 | // 0 and M-1. The function also takes increment (C) and seed parameters (S). 174 | // The increment should be odd to increase uniformity. 175 | // 176 | rand_int_par(1, M, C, S) = 177 | (S + C) * 1103515245 & 4294967295 : abs : %(M); 178 | rand_int_par(N, M, C, S) = 179 | (S + C) * 1103515245 & 4294967295 : abs : %(M) , 180 | rand_int_par(N - 1, M, C, (S + C) * 1103515245 & 4294967295); 181 | // ----------------------------------------------------------------------------- 182 | 183 | // ----------------------------------------------------------------------------- 184 | // Topology selection for genes interactions. This function takes an int, N, 185 | // representing the order of the network, the inputs number in each gene, K, 186 | // and a seed, S. The function generates homogeneous topologies, that is, 187 | // genes interactions where individual gene contributions are equally but 188 | // randomly distributed throughout the network. N and K should be pow-of-2 189 | // for maximum homogeneity. 190 | // The seed should be a positive int roughly below 2^16. 191 | // 192 | topology(N, K, S) = 193 | si.bus(N) <: 194 | par(i, N * K, si.bus(N) <: 195 | ba.selector(ba.take(i + 1, routes), N * K)) 196 | with { 197 | routes = lcg_par(N * K, N * K, 5, 15, S); 198 | }; 199 | // ----------------------------------------------------------------------------- 200 | 201 | // ----------------------------------------------------------------------------- 202 | // Random Boolean networks generator. The function takes four ints, N, K, S_1, 203 | // and S_2, respectively for the network order (pow-of-2), genes inputs, 204 | // the seed for the genes array, the seed for the topology type, and a list 205 | // of numbers determining the delays in samples for each feedback path. The function also 206 | // provides a slider to expand or compress the delays. 207 | // 208 | rbn(N, K, S_1, S_2, del_seq) = 209 | genes2(N, K, S_1) 210 | ~ (delays(N, del_seq) : topology(N, K, S_2)); 211 | // ----------------------------------------------------------------------------- 212 | 213 | // full_adder(x1[n], x2[n], c_in[n]); ------------------------------------------ 214 | // 215 | // (author: Dario Sanfilippo) 216 | // 217 | // Adder for binary values. It adds two operands as well as a carrier 218 | // input. It outputs the sum as well as the carrier output. 219 | // 220 | // 3 inputs: 221 | // x1[n], first operand; 222 | // x2[n], second operand; 223 | // c_in[n], carrier input. 224 | // 225 | // 2 outputs: 226 | // s_out[n], resulting sum; 227 | // c_out[n], carrier output. 228 | // 229 | full_adder(x1, x2, c_in) = s_out , 230 | c_out 231 | with { 232 | s_out = xor(rint(c_in), xor(rint(x1), rint(x2))); 233 | c_out = (rint(c_in) & xor(rint(x1), rint(x2))) | 234 | (rint(x1) & rint(x2)); 235 | }; 236 | // ----------------------------------------------------------------------------- 237 | 238 | // bitstream_adder(x1[n], x2[n]); ---------------------------------------------- 239 | // 240 | // (author: Dario Sanfilippo) 241 | // 242 | // Adder for delta-sigma-modulated streams. 243 | // 244 | // 2 inputs: 245 | // x1[n], first bitstream; 246 | // x2[n], second bitstream. 247 | // 248 | // 1 outputs: 249 | // y[n], resulting bitstream summation. 250 | // 251 | bitstream_adder(x1, x2) = loop 252 | ~ _ : ! , 253 | _ 254 | with { 255 | loop(fb) = full_adder(x1, x2, fb); 256 | }; 257 | // ----------------------------------------------------------------------------- 258 | 259 | // ----------------------------------------------------------------------------- 260 | // Binary summing bus of N inputs. 261 | // 262 | bitstream_adderN(1) = _; 263 | bitstream_adderN(2) = bitstream_adder; 264 | bitstream_adderN(N) = bitstream_adderN(N - 1) , 265 | _ : bitstream_adder; 266 | // ----------------------------------------------------------------------------- 267 | 268 | // ----------------------------------------------------------------------------- 269 | // N-delay array. 270 | // 271 | delays(N, sequence) = 272 | par(i, N, rint(de.fdelay(ba.take(i + 1, sequence), 273 | abs((ba.take(i + 1, sequence) * factor) % ba.take(i + 1, sequence))))) 274 | with { 275 | factor = 16 ^ hslider("delays stretching", 0, -1, 1, .001); 276 | }; 277 | // ----------------------------------------------------------------------------- 278 | 279 | // ----------------------------------------------------------------------------- 280 | // Lists of number sequences for delay lines. 281 | // 282 | seq_primes = 283 | (2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53); 284 | seq_fibonacci = 285 | (1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987); 286 | seq_hexagonal = 287 | (1, 6, 15, 28, 45, 66, 91, 120, 153, 190, 231, 276, 325, 378, 435, 496); 288 | seq_lazycaterer = 289 | (1, 2, 4, 7, 11, 16, 22, 29, 37, 46, 56, 67, 79, 92, 106, 121); 290 | seq_magic = 291 | (15, 34, 65, 111, 175, 260, 369, 505, 671, 870, 1105, 1379, 1695, 2056, 292 | 2465, 2925); 293 | seq_pentagonal = 294 | (1, 2, 5, 7, 12, 15, 22, 26, 35, 40, 51, 57, 70, 77, 92, 100); 295 | seq_square = 296 | (1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121, 144, 169, 196, 225, 256); 297 | seq_triangular = 298 | (1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 66, 78, 91, 105, 120, 136); 299 | // ----------------------------------------------------------------------------- 300 | 301 | // ----------------------------------------------------------------------------- 302 | // Process example. 303 | // 304 | // Try stretch values 0.042 or -0.037. 305 | // 306 | // N = 8; 307 | // K = 8; 308 | // process = 309 | // rbn(N, K, 316, 153, seq_hexagonal) : par(i, 2, bitstream_adderN(N / 2)); 310 | // ----------------------------------------------------------------------------- 311 | 312 | // ----------------------------------------------------------------------------- 313 | // Process example. 314 | // 315 | N = 16; // genes array size 316 | K = 8; // genes input size 317 | process = 318 | rbn(N, K, 231, 415, seq_fibonacci) : par(i, 2, bitstream_adderN(N / 2)); 319 | // ----------------------------------------------------------------------------- 320 | -------------------------------------------------------------------------------- /lib/bitDSP_int32.lib: -------------------------------------------------------------------------------- 1 | declare name "bitDSP_int32"; 2 | declare author "LFSaw (Till Bovermann), Dario Sanfilippo"; 3 | declare copyright "MIT"; 4 | 5 | // bit = library("bitDSP"); // main library 6 | // bit32 = library("bitDSP_int32"); // int32-based library 7 | // bitBus = library("bitDSP_bitBus"); // int32-based library 8 | bitConv = library("bitDSP_conversion"); // conversion between formats library 9 | 10 | // sc = library("scUGens.lib"); // part of https://github.com/tai-studio/faust-sc 11 | // lf = library("taiStudio.lib"); // part of https://github.com/tai-studio/faust-sc 12 | 13 | // import("stdfaust.lib"); 14 | // only import what is necessary 15 | // 16 | // an = library("analyzers.lib"); 17 | ba = library("basics.lib"); 18 | // co = library("compressors.lib"); 19 | de = library("delays.lib"); 20 | // dm = library("demos.lib"); 21 | // dx = library("dx7.lib"); 22 | // en = library("envelopes.lib"); 23 | // fi = library("filters.lib"); 24 | // ho = library("hoa.lib"); 25 | // it = library("interpolators.lib"); 26 | ma = library("maths.lib"); 27 | // mi = library("mi.lib"); 28 | // ef = library("misceffects.lib"); 29 | // os = library("oscillators.lib"); 30 | // no = library("noises.lib"); 31 | // pf = library("phaflangers.lib"); 32 | // pl = library("platform.lib"); 33 | // pm = library("physmodels.lib"); 34 | // rm = library("reducemaps.lib"); 35 | // re = library("reverbs.lib"); 36 | // ro = library("routes.lib"); 37 | // sp = library("spats.lib"); 38 | si = library("signals.lib"); 39 | // so = library("soundfiles.lib"); 40 | // sy = library("synths.lib"); 41 | // ve = library("vaeffects.lib"); 42 | // wa = library("webaudio.lib"); 43 | // sf = library("all.lib"); 44 | // vl = library("version.lib"); 45 | 46 | 47 | 48 | ///////////////////// generic bit operations /////////////////////////////// 49 | 50 | //---------------------------------`(bit32.)bitNot`--------------------------------------- 51 | // 52 | // (author: Till Bovermann) 53 | // 54 | // bitwise Not 55 | // 56 | // note: relies on foreign functions (c-based platforms only) 57 | // 58 | // 59 | // #### Usage 60 | // 61 | // ``` 62 | // 16: bitNot 63 | // ``` 64 | //----------------------------------------------------------------------------- 65 | bitNot = ffunction(int bit_not (int), "bitDSP.h", ""); 66 | 67 | //---------------------------------`(bit32.)left_shift`--------------------------------------- 68 | // 69 | // (author: Till Bovermann) 70 | // 71 | // unsigned left shift operator 72 | // 73 | // note: relies on foreign functions (c-based platforms only) 74 | // 75 | // 76 | // #### Usage 77 | // 78 | // ``` 79 | // _ : left_shift(_) 80 | // ``` 81 | //----------------------------------------------------------------------------- 82 | left_shift = ffunction(int bit_leftShift (int, int), "bitDSP.h", ""); 83 | 84 | 85 | //---------------------------------`(bit32.)right_shift`--------------------------------------- 86 | // 87 | // (author: Till Bovermann) 88 | // 89 | // unsigned right shift operator 90 | // 91 | // note: relies on foreign functions (c-based platforms only) 92 | // 93 | // 94 | // #### Usage 95 | // 96 | // ``` 97 | // _ : right_shift(_) 98 | // ``` 99 | //----------------------------------------------------------------------------- 100 | right_shift = ffunction(int bit_rightShift (int, int), "bitDSP.h", ""); 101 | 102 | ////////////////////////// bit operations on parts of the bits 103 | 104 | //---------------------------------`(bit32.)maskedNot`--------------------------------------- 105 | // 106 | // (author: Till Bovermann) 107 | // 108 | // invert selected bits of an integer 109 | // 110 | // note: relies on foreign functions (c-based platforms only) 111 | // 112 | // 113 | // #### Usage 114 | // 115 | // ``` 116 | // maskedNot(mask, in) 117 | // ``` 118 | // TODO: wait for bitNOT implementation 119 | //----------------------------------------------------------------------------- 120 | // maskedNot(mask, in) = (mask & bitNot(in)) | (bitNot(mask) & in); 121 | maskedNot(mask, in) = applyMask(bitNot(in), a, mask); 122 | 123 | 124 | //---------------------------------`(bit32.)maskedAnd`--------------------------------------- 125 | // 126 | // (author: Till Bovermann) 127 | // 128 | // bit-wise AND of selected bits of two integers. remaining bits are kept from first parameter 129 | // 130 | // #### Usage 131 | // 132 | // ``` 133 | // maskedAnd(mask, a, b) 134 | // ``` 135 | // TODO: wait for bitNOT implementation 136 | //----------------------------------------------------------------------------- 137 | maskedAnd(mask, a, b) = applyMask(a&b, a, mask); 138 | 139 | 140 | //---------------------------------`(bit32.)maskedOr`--------------------------------------- 141 | // 142 | // (author: Till Bovermann) 143 | // 144 | // bit-wise OR of selected bits of two integers. remaining bits are kept from first parameter 145 | // 146 | // #### Usage 147 | // 148 | // ``` 149 | // maskedOr(mask, a, b) 150 | // ``` 151 | // TODO: wait for bitNOT implementation 152 | //----------------------------------------------------------------------------- 153 | maskedOr(mask, a, b) = applyMask(a|b, a, mask); 154 | 155 | 156 | //---------------------------------`(bit32.)maskedXor`--------------------------------------- 157 | // 158 | // (author: Till Bovermann) 159 | // 160 | // bit-wise OR of selected bits of two integers. remaining bits are kept from first parameter 161 | // 162 | // #### Usage 163 | // 164 | // ``` 165 | // maskedXor(mask, a, b) 166 | // ``` 167 | // TODO: wait for bitNOT implementation 168 | //----------------------------------------------------------------------------- 169 | maskedXor(mask, a, b) = applyMask(xor(a,b), a, mask); 170 | 171 | 172 | //---------------------------------`(bit32.)applyMask`--------------------------------------- 173 | // 174 | // (author: Till Bovermann) 175 | // 176 | // apply result only to selected bits 177 | // 178 | // #### Usage 179 | // 180 | // ``` 181 | // applyMask(res, org, mask) 182 | // ``` 183 | // TODO: wait for bitNOT implementation 184 | //----------------------------------------------------------------------------- 185 | applyMask(res, org, mask) = (mask & res) | (bitNot(mask) & orig); 186 | 187 | 188 | ////////////////////////// delays ///////////////////////////////////////////////////// 189 | 190 | //---------------------------------`(bit32.)delay32`--------------------------------------- 191 | // 192 | // (author: Till Bovermann) 193 | // 194 | // single-bit delay on an integer bitstream. maximum of 32bit delays possible. 195 | // 196 | // note: relies on foreign functions (c-based platforms only) 197 | // 198 | // #### Usage 199 | // 200 | // ``` 201 | // delay32(delta, _) 202 | // ``` 203 | //----------------------------------------------------------------------------- 204 | delay32(0, x) = x; 205 | delay32(delta, x) = (right_shift(x, delta) | left_shift(x', (32-delta))); 206 | 207 | 208 | //---------------------------------`(bit32.)delay`--------------------------------------- 209 | // 210 | // (author: Till Bovermann) 211 | // 212 | // single-bit delay on integer bitstream 213 | // 214 | // #### Usage 215 | // 216 | // ``` 217 | // delay(delta, _) 218 | // ``` 219 | //----------------------------------------------------------------------------- 220 | delay(delta, x) = delay32((delta % 32), x@( (delta, 32) : div )); 221 | 222 | 223 | //////////////////////////////// utilities ////////////////////////////// 224 | 225 | 226 | int_min = fconstant(int INT_MIN, ); 227 | int_max = fconstant(int INT_MAX, ); 228 | 229 | //---------------------------------`(bit32.)bit_mask`--------------------------------------- 230 | // 231 | // (author: Till Bovermann) 232 | // 233 | // create bit mask with indices at list values == 1 234 | // 235 | // note: relies on foreign functions (c-based platforms only) 236 | // 237 | // #### Usage 238 | // 239 | // ``` 240 | // bit_mask(si.bus(N)) : _ 241 | // ``` 242 | //----------------------------------------------------------------------------- 243 | bit_mask((n, ns)) = bit_mask(ns) | left_shift(1, n); 244 | bit_mask(n) = left_shift(1, n); 245 | 246 | //---------------------------------`(bit32.)parity`--------------------------------------- 247 | // 248 | // (author: Till Bovermann) 249 | // 250 | // compute parity of a 32bit integer (assuming it to be unsigned) 251 | // 252 | // note: relies on foreign functions (c-based platforms only) 253 | // 254 | // #### Usage 255 | // 256 | // ``` 257 | // _ : parity : _ 258 | // ``` 259 | //----------------------------------------------------------------------------- 260 | parity = ffunction(int parity (int), "bitDSP.h", ""); 261 | 262 | //---------------------------------`(bit32.)div`--------------------------------------- 263 | // integer division 264 | // 265 | // (author: Till Bovermann) 266 | // 267 | // note: relies on foreign functions (c-based platforms only) 268 | // 269 | // 270 | // #### Usage 271 | // 272 | // ``` 273 | // 31, 32: div 274 | // div(31, 32) 275 | // ``` 276 | //----------------------------------------------------------------------------- 277 | div = ffunction(int div_i (int, int), "bitDSP.h", ""); 278 | 279 | ////////////////////////// oscillators //////////////////////// 280 | 281 | //---------------------------------`(bit32.)lfsr32`--------------------------------------- 282 | // 283 | // (author: Till Bovermann) 284 | // 285 | // Compute LFSR on a 32bit integer bitset (assuming it to be unsigned). 286 | // Resets on changed input state. 287 | // See https://en.wikipedia.org/wiki/Linear-feedback_shift_register for details on LFSRs. 288 | // 289 | // note: relies on foreign functions (c-based platforms only) 290 | // 291 | // 292 | // #### Usage 293 | // 294 | // ``` 295 | // _ : lfsr32(mask) : _ 296 | // ``` 297 | // with 298 | // + `mask` — determining which bits to consider for the parity computation 299 | //----------------------------------------------------------------------------- 300 | lfsr32(mask, in) = step(mask, in) ~ _ with { 301 | step(mask, in, fbIn) = select_on_change(in, fbIn) <: (parity(_ & mask), left_shift(_, 1)) : |; 302 | select_on_change(a, b) = select2(changed(a), b, a); 303 | changed(x) = x != x'; 304 | }; 305 | 306 | 307 | //---------------------------------`(bit32.)lfsr`--------------------------------------- 308 | // 309 | // (author: Till Bovermann) 310 | // 311 | // Compute LFSR on an n-bit integer bitset (assuming it to be unsigned). 312 | // Resets on changed input state. 313 | // See https://en.wikipedia.org/wiki/Linear-feedback_shift_register for details on LFSRs. 314 | // 315 | // note: relies on foreign functions (c-based platforms only) 316 | // 317 | // 318 | // #### Usage 319 | // 320 | // ``` 321 | // _ : lfsr(n, mask) : _ 322 | // ``` 323 | // with 324 | // + `n` — number of bits the LFSR is operating on 325 | // + `mask` — determining which bits to consider for the parity computation 326 | //----------------------------------------------------------------------------- 327 | lfsr(n, mask, in) = step(n, mask, in) ~ _ with { 328 | masked_out(n, val) = right_shift(-1, 32-n) & val; 329 | step(n, mask, in, fbIn) = select_on_change(in, fbIn) <: (parity(_ & mask), masked_out(n, left_shift(_, 1))) : |; 330 | select_on_change(a, b) = select2(changed(a), b, a); 331 | changed(x) = x != x'; 332 | }; 333 | 334 | 335 | 336 | //////////////////////// DACs //////////////////////////////////////////// 337 | 338 | //---------------------------------`(bit32.)bitDAC_i`--------------------------------------- 339 | // 340 | // (author: Till Bovermann) 341 | // 342 | // select bits of an integer to be interpreted as PCM values 343 | // range is [0, 1, .. (2^size)[ 344 | // 345 | // note: relies on foreign functions (c-based platforms only) 346 | // 347 | // #### Usage 348 | // 349 | // ``` 350 | // bitDAC_i(8, 2, _) 351 | // ``` 352 | //----------------------------------------------------------------------------- 353 | bitDAC_i(offset, size, in) = right_shift((in & bitmask), offset) // shift selection to right-most bits 354 | with { 355 | maxval = left_shift(1,size)-1; // maximum value that fits into size 356 | bitmask = left_shift(maxval, offset); // mask selects area of which to create PCM values 357 | }; 358 | 359 | 360 | //---------------------------------`(bit32.)bitDAC`--------------------------------------- 361 | // 362 | // (author: Till Bovermann) 363 | // 364 | // select bits of an integer to be interpreted as PCM values 365 | // range is [0.f .. 1] 366 | // 367 | // note: relies on foreign functions (c-based platforms only) 368 | // 369 | // #### Usage 370 | // 371 | // ``` 372 | // bitDAC(8, 2, _) 373 | // ``` 374 | // 375 | // #### Example: 6-bit noise 376 | // 377 | // ``` 378 | // bitDAC(6, 0, int(no.noise * 10)); 379 | // ``` 380 | //----------------------------------------------------------------------------- 381 | bitDAC(offset, size, in) = normed(right_shift((in & bitmask), offset)) // shift selection to right-most bits 382 | with { 383 | maxval = min(left_shift(1,size)-1, 31); // maximum value that fits into size 384 | bitmask = left_shift(maxval, offset); // mask selects area of which to create PCM values 385 | normed(out) = out / (maxval-1); // normalise values to be between 0 and 1 (excl.) 386 | }; 387 | 388 | 389 | //---------------------------------`(bit32.)dsm1_32`--------------------------------------- 390 | // 391 | // (author: Till Bovermann) 392 | // 393 | // delta-sigma converter for a float-encoded multibit-stream. 394 | // It turns the incoming signal into a binary stream packed into chuncks of a 32bit integer signal. 395 | // 396 | // 397 | // #### Usage 398 | // 399 | // ``` 400 | // _ : dsm1_32 : _; 401 | // ``` 402 | // with 403 | // + input a float signal in the range [-1, 1] 404 | // + output a binary stream split into chuncks of 32 values packed in 32bit integers, thus resulting in 32x oversampling. 405 | dsm1_32 = dsm1(32); // version fixed to 32bit output encoding 406 | // dsm1(N) = dsm1_ff_path(N) ~ si.bus(outputs(dsm1_one_step)-1) : par(i, outputs(dsm1_one_step)-1, !), _; 407 | dsm1(N) = _, 0 : dsm1_ff_path(N) ~ si.bus(outputs(dsm1_one_step)-2) : par(i, outputs(dsm1_one_step)-1, !), _ 408 | with { 409 | // --------- dsm1_one_step 410 | // compute one sample dsm1 and pass around state. 411 | // x — input, 412 | // out_prev — (previous) output, 413 | // first params (s0, s1) are internal states 414 | // in order for correct unfolding of operators, it is required to write n-dimensional 415 | // function as lambda-statement. 416 | // 417 | // single application with initial states == 0 418 | // process = par(i, outputs(dsm1_one_step)-1, 0), _ : dsm1_one_step : par(i, outputs(dsm1_one_step)-1, !), _; 419 | // (time-recursive) feedback application 420 | // process = -1, 0 : dsm1_one_step ~ si.bus(outputs(dsm1_one_step)-2) : !, !, !, _; 421 | dsm1_one_step = \(s0_prev, s1_prev, x, out_prev).(s0, s1, x, out 422 | with { 423 | s0 = x - s1_prev + s0_prev; 424 | s1 = s0 >=0 : select2(_, -1, 1); // bi-modal (for computation) 425 | out = s1 > 0; // make uni-modal 426 | }); 427 | 428 | // --------- oversample_snh 429 | // oversample with sample and hold 430 | // f needs to have a list as argument, with 431 | // + first element being the output of the last evaluation, 432 | // + previous list items are (optional) intermediate states. 433 | // + last list item is the input. 434 | // 435 | // process = 0.5 : \(x).(oversample_snh(3, dsm1_one_step, (0, 1, x, 3))); 436 | // 437 | oversample_snh(1, func, x) = x : func; 438 | oversample_snh(N, func, x) = oversample_snh(N-1, func, y(func, x)), y_out(func, x) 439 | with { 440 | y(func, x) = x : func; 441 | // block everything but last value (i.e. output) 442 | y_out(func, x) = y(func, x) : par(i, outputs(func)-1, !), _; 443 | }; 444 | 445 | // --------- dsm1_ff_path 446 | // feed-forward path of N calculations 447 | // FIXME: allow arbitrary number `N` of intermediate fbck channels 448 | // see [\[Faudiostream-users\] arbitrary channels to recursive definition?](hook://email/C187E198-7DCB-496D-80CB-39C94EC6F1F6%40lfsaw.de) 449 | // 450 | // process = 0, 0, -0.4, 0 : dsm1_ff_path(1); 451 | // process = _, 0 : dsm1_ff_path(3) ~ si.bus(outputs(dsm1_one_step)-2) : par(i, outputs(dsm1_one_step)-1, !), _; 452 | // 453 | dsm1_ff_path(N) = \(s0, s1, x, out_prev).(oversample_snh(N, dsm1_one_step, (s0, s1, x, out_prev))) : si.bus(numVars), bitConv.bitBus_to_int(N) 454 | with { 455 | numVars = outputs(dsm1_one_step)-1; 456 | }; 457 | }; 458 | 459 | 460 | //////////////////////// debug ///////////////////////////////////////// 461 | 462 | //---------------------------------`(bit32.)print`--------------------------------------- 463 | // 464 | // (author: Till Bovermann) 465 | // 466 | // print an integer as a bit representation 467 | // 468 | // note: relies on foreign functions (c-based platforms only) 469 | // 470 | // 471 | // #### Usage 472 | // 473 | // ``` 474 | // _ : print 475 | // ``` 476 | //----------------------------------------------------------------------------- 477 | print = ffunction(int bit_print (int), "bitDSP.h", ""); 478 | 479 | 480 | 481 | //---------------------------------`(bit32.)print2`--------------------------------------- 482 | // 483 | // (author: Till Bovermann) 484 | // 485 | // print an integer as a bit representation, including two slots for (integer) counters. 486 | // useful to output sample and channel count. 487 | // 488 | // note: relies on foreign functions (c-based platforms only) 489 | // 490 | // 491 | // #### Usage 492 | // 493 | // ``` 494 | // _ : print2(_, _) 495 | // ``` 496 | //----------------------------------------------------------------------------- 497 | print2 = ffunction(int bit_print2counters (int, int, int), "bitDSP.h", ""); 498 | -------------------------------------------------------------------------------- /lib/bitDSP.lib: -------------------------------------------------------------------------------- 1 | declare name "bitDSP"; 2 | declare author "LFSaw (Till Bovermann), Dario Sanfilippo"; 3 | declare copyright "MIT"; 4 | 5 | // bit = library("bitDSP.lib"); // main library 6 | // bit32 = library("bitDSP_int32.lib"); // int32-based library 7 | // bitBus = library("bitDSP_binBus.lib"); // int32-based library 8 | bitConv = library("bitDSP_conversion.lib"); // conversion between formats library 9 | 10 | // sc = library("scUGens.lib"); // part of https://github.com/tai-studio/faust-sc 11 | // lf = library("taiStudio.lib"); // part of https://github.com/tai-studio/faust-sc 12 | 13 | // import("stdfaust.lib"); 14 | // only import what is necessary 15 | // 16 | // an = library("analyzers.lib"); 17 | ba = library("basics.lib"); 18 | // co = library("compressors.lib"); 19 | de = library("delays.lib"); 20 | // dm = library("demos.lib"); 21 | // dx = library("dx7.lib"); 22 | // en = library("envelopes.lib"); 23 | fi = library("filters.lib"); 24 | // ho = library("hoa.lib"); 25 | // it = library("interpolators.lib"); 26 | ma = library("maths.lib"); 27 | // mi = library("mi.lib"); 28 | // ef = library("misceffects.lib"); 29 | os = library("oscillators.lib"); 30 | // no = library("noises.lib"); 31 | // pf = library("phaflangers.lib"); 32 | // pl = library("platform.lib"); 33 | // pm = library("physmodels.lib"); 34 | // rm = library("reducemaps.lib"); 35 | // re = library("reverbs.lib"); 36 | ro = library("routes.lib"); 37 | // sp = library("spats.lib"); 38 | si = library("signals.lib"); 39 | // so = library("soundfiles.lib"); 40 | // sy = library("synths.lib"); 41 | // ve = library("vaeffects.lib"); 42 | // wa = library("webaudio.lib"); 43 | // sf = library("all.lib"); 44 | // vl = library("version.lib"); 45 | 46 | /////////////////////////// oscillators 47 | 48 | //---------------------------------`(bit.)silence`--------------------------------------- 49 | // 50 | // (author: Till Bovermann) 51 | // 52 | // by definition, silence is the alteration of the two binary states at nyquist frequency 53 | // 54 | // 55 | // 56 | // #### Usage 57 | // 58 | // ``` 59 | // silence : _; // bimodal, i.e. between [-1, 1] 60 | // ``` 61 | //----------------------------------------------------------------------------- 62 | silence = dirac : fb(_) ~ _ with { 63 | dirac = 1-1'; 64 | fb(init, x) = -x + init; 65 | }; 66 | 67 | 68 | // bool_osc0(del1[n], del2[n], del3[n], del4[n]); ------------------------------ 69 | // 70 | // (author: Dario Sanfilippo) 71 | // 72 | // Basic Boolean oscillator with four cross-coupled nodes, mainly for 73 | // chaotic oscillations including limit cycles and strange attractors. 74 | // 75 | // The future development of this approach could be to have a set of 76 | // nodes with specific Boolean processes that can be combined in 77 | // networks of arbitrary sizes and topology by simple argument 78 | // specification. 79 | // 80 | // 4 inputs: 81 | // del1[n], delay of the output of the first node up to SR samples; 82 | // del2[n], delay of the output of the second node up to SR samples; 83 | // del3[n], delay of the output of the third node up to SR samples; 84 | // del4[n], delay of the output of the fourth node up to SR samples; 85 | // 86 | // 1 outputs: 87 | // y[n], first node; 88 | // 89 | bool_osc0(del1, del2, del3, del4) = node1 90 | letrec { 91 | 'node1 = not(node1 & node2) @ max(0, min(ma.SR, del1)); 92 | 'node2 = not(node2 | node3) @ max(0, min(ma.SR, del2)); 93 | 'node3 = not(node3 xor node4) @ max(0, min(ma.SR, del3)); 94 | 'node4 = not(node4 & node1) @ max(0, min(ma.SR, del4)); 95 | } 96 | with { 97 | not(x) = rint(1 - x); 98 | }; 99 | // ----------------------------------------------------------------------------- 100 | 101 | // bool_osc1(del1[n], del2[n]); ------------------------------------------------ 102 | // 103 | // (author: Dario Sanfilippo) 104 | // 105 | // Basic Boolean oscillator with two cross-coupled nodes, mainly for 106 | // chaotic oscillations including limit cycles and strange attractors. 107 | // 108 | // The future development of this approach could be to have a set of 109 | // nodes with specific Boolean processes that can be combined in 110 | // networks of arbitrary sizes and topology by simple argument 111 | // specification. 112 | // 113 | // 2 inputs: 114 | // del1[n], delay of the output of the first node up to SR samples; 115 | // del2[n], delay of the output of the second node up to SR samples; 116 | // 117 | // 1 outputs: 118 | // y[n], first node; 119 | // 120 | bool_osc1(del1, del2) = node1 121 | letrec { 122 | 'node1 = not(node1 xor node2 & node1) @ max(0, min(ma.SR, del1)); 123 | 'node2 = not(node2 xor node1 xor node2) @ max(0, min(ma.SR, del2)); 124 | } 125 | with { 126 | not(x) = 1 - x; 127 | }; 128 | // ----------------------------------------------------------------------------- 129 | 130 | // bool_osc2(del1[n], del2[n]); ------------------------------------------------ 131 | // 132 | // (author: Dario Sanfilippo) 133 | // 134 | // Basic Boolean oscillator with two cross-coupled nodes, mainly for 135 | // chaotic oscillations including limit cycles and strange attractors. 136 | // 137 | // The future development of this approach could be to have a set of 138 | // nodes with specific Boolean processes that can be combined in 139 | // networks of arbitrary sizes and topology by simple argument 140 | // specification. 141 | // 142 | // 2 inputs: 143 | // del1[n], delay of the output of the first node up to SR samples; 144 | // del2[n], delay of the output of the second node up to SR samples; 145 | // 146 | // 1 outputs: 147 | // y[n], first node; 148 | // 149 | bool_osc2(del1, del2) = node1 150 | 151 | letrec { 152 | 'node1 = not(node1 & node2) @ max(0, min(ma.SR, del1)); 153 | 'node2 = not(node1 & node2) @ max(0, min(ma.SR, del2)); 154 | } 155 | with { 156 | not(x) = rint(1 - x); 157 | }; 158 | // ----------------------------------------------------------------------------- 159 | 160 | // cic(N, CF[n], x[n]); -------------------------------------------------------- 161 | // 162 | // (author: Dario Sanfilippo) 163 | // 164 | // Comb-integrator circuit lowpass filter. 165 | // Based on Eric Lyon's: https://www.dsprelated.com/showarticle/1337.php. 166 | // 167 | // 2 inputs: 168 | // CF[n], cut-off frequency in Hz; 169 | // x[n]. 170 | // 171 | // 1 outputs: 172 | // y[n], lowpassed x[n]. 173 | // 174 | // 1 compile-time arguments: 175 | // "N", (integer) order of the filter. 176 | // 177 | cic(N, cf, x) = x : seq(i, N, delta(1, .5 / cf) : 178 | fi.pole(1)) / (.5 / cf * ma.SR) ^ N; 179 | // ----------------------------------------------------------------------------- 180 | 181 | 182 | // delta(S, dt[n], x[n]); ------------------------------------------------------ 183 | // 184 | // (author: Dario Sanfilippo) 185 | // 186 | // First derivative using linear interpolation delay lines, hence 187 | // allowing fractional differentiation periods. 188 | // 189 | // 2 inputs: 190 | // dt[n], differentiation period in seconds; 191 | // x[n]. 192 | // 193 | // 1 outputs: 194 | // y[n], first derivative of x[n]. 195 | // 196 | // 1 compile-time arguments: 197 | // S, maximum differentiation period in seconds. 198 | // 199 | delta(S, dt, in) = in - de.fdelay(S * ma.SR, dt * ma.SR, in); 200 | // ----------------------------------------------------------------------------- 201 | 202 | // dsm1(x[n]); ----------------------------------------------------------------- 203 | // 204 | // (author: Till Bovermann) 205 | // 206 | // First-order digital delta-sigma modulator. 207 | // 208 | // 1 inputs: 209 | // x[n]; 210 | // 211 | // 1 outputs: 212 | // y[n], modulated input in the range [-1; 1]. 213 | // 214 | dsm1(x) = loop 215 | ~ _ 216 | with { 217 | loop(fb) = x - fb : posFB > 0 : select2(_, -1, 1); 218 | posFB(fb) = (_, fb : +) ~ _; 219 | }; 220 | // ----------------------------------------------------------------------------- 221 | 222 | // ddsm1(x[n]); ----------------------------------------------------------------- 223 | // 224 | // (author: Dario Sanfilippo) 225 | // 226 | // First-order digital delta-sigma modulator, alternat implementation. 227 | // 228 | // 1 inputs: 229 | // x[n]; 230 | // 231 | // 1 outputs: 232 | // y[n], modulated input in the range [-1; 1]. 233 | // 234 | ddsm1(x) = y 235 | letrec { 236 | 'y = ba.if(fi.pole(1, x - y) < 0, -1, 1); 237 | }; 238 | // ----------------------------------------------------------------------------- 239 | 240 | // dsm2(x[n]); ----------------------------------------------------------------- 241 | // 242 | // (author: Dario Sanfilippo) 243 | // 244 | // Second-order digital delta-sigma modulator. 245 | // 246 | // 1 inputs: 247 | // x[n]; 248 | // 249 | // 1 outputs: 250 | // y[n], modulated input in the range [-1; 1]. 251 | // 252 | dsm2(x) = loop 253 | ~ _ 254 | with { 255 | loop(fb) = x - fb : fi.pole(1) - 2 * fb : fi.pole(1) : Q; 256 | Q(z) = select2(z < 0, 1, -1); 257 | }; 258 | // ----------------------------------------------------------------------------- 259 | 260 | // ----------------------------------------------------------------------------- 261 | // 262 | // (author: Dario Sanfilippo) 263 | // 264 | // First and second-order dsm with gain input. 265 | // 266 | ddsm1G(G, x) = y 267 | letrec { 268 | 'y = ba.if(fi.pole(1, x - y * G) < 0, -1, 1); 269 | }; 270 | ddsm2G(G, x) = loop 271 | ~ _ 272 | with { 273 | loop(fb) = Q(fi.pole(1, fi.pole(1, x - fb * G) - 2 * fb * G)); 274 | Q(z) = select2(z < 0, 1, -1); 275 | }; 276 | // ----------------------------------------------------------------------------- 277 | 278 | // ----------------------------------------------------------------------------- 279 | // 280 | // (author: Dario Sanfilippo) 281 | // 282 | // First and second-order summing busses. N is the number of signals being 283 | // summed. 284 | // 285 | summing1(N) = si.bus(N) :> ddsm1G(N); 286 | summing2(N) = si.bus(N) :> ddsm2G(N); 287 | // ----------------------------------------------------------------------------- 288 | 289 | // full_adder(x1[n], x2[n], c_in[n]); ------------------------------------------ 290 | // 291 | // (author: Dario Sanfilippo) 292 | // 293 | // Adder for binary values. It adds two operands as well as a carrier 294 | // input. It outputs the sum as well as the carrier output. 295 | // 296 | // 3 inputs: 297 | // x1[n], first operand; 298 | // x2[n], second operand; 299 | // c_in[n], carrier input. 300 | // 301 | // 2 outputs: 302 | // s_out[n], resulting sum; 303 | // c_out[n], carrier output. 304 | // 305 | full_adder(x1, x2, c_in) = s_out , 306 | c_out 307 | with { 308 | s_out = xor(rint(c_in), xor(rint(x1), rint(x2))); 309 | c_out = (rint(c_in) & xor(rint(x1), rint(x2))) | 310 | (rint(x1) & rint(x2)); 311 | }; 312 | // ----------------------------------------------------------------------------- 313 | 314 | // bitstream_adder(x1[n], x2[n]); ---------------------------------------------- 315 | // 316 | // (author: Dario Sanfilippo) 317 | // 318 | // Adder for delta-sigma-modulated streams. 319 | // 320 | // 2 inputs: 321 | // x1[n], first bitstream; 322 | // x2[n], second bitstream. 323 | // 324 | // 1 outputs: 325 | // y[n], resulting bitstream summation. 326 | // 327 | bitstream_adder(x1, x2) = loop 328 | ~ _ : ! , 329 | _ 330 | with { 331 | loop(fb) = full_adder(x1, x2, fb); 332 | }; 333 | // ----------------------------------------------------------------------------- 334 | 335 | // ----------------------------------------------------------------------------- 336 | // 337 | // (author: Dario Sanfilippo) 338 | // 339 | // Clipped integrator with state-reset input: 1 to reset, 0 to accumulate. 340 | // 341 | int_clip_r(reset, low, high, x) = clip(low, high, +(x)) ~ *(1 - reset); 342 | // ----------------------------------------------------------------------------- 343 | 344 | // ----------------------------------------------------------------------------- 345 | // 346 | // (author: Dario Sanfilippo) 347 | // 348 | // First-order dsm with clipped and reset-state integrator; G is the ddsm gain. 349 | // 350 | ddsm1_clip_r(reset, low, high, G, x) = y 351 | letrec { 352 | 'y = ba.if(int_clip_r(reset, low, high, x - G * y) < 0, -1, 1); 353 | }; 354 | // ----------------------------------------------------------------------------- 355 | 356 | // ----------------------------------------------------------------------------- 357 | // 358 | // (author: Dario Sanfilippo) 359 | // 360 | // First-order dsm integrator with clipping and reset-state. 361 | // 362 | int1bit_clip_r(reset, low, high, G, x) = 363 | ddsm1_clip_r(reset, low, high, G, int_clip_r(reset, low, high, x)); 364 | // ----------------------------------------------------------------------------- 365 | 366 | // ----------------------------------------------------------------------------- 367 | // First-order clipped with reset ddsm lowpass. 368 | // 369 | lp1bit_clip_r(reset, low, high, G, cf, x) = y 370 | letrec { 371 | 'y = int1bit_clip_r(reset, low, high, G, (x - y) * cf); 372 | }; 373 | // ----------------------------------------------------------------------------- 374 | 375 | // ----------------------------------------------------------------------------- 376 | // 377 | // (author: Dario Sanfilippo) 378 | // 379 | // First-order clipped with reset ddsm highpass. 380 | // 381 | hp1bit_clip_r(reset, low, high, G, cf, x) = 382 | ddsm1_clip_r(reset, low, high, G, x - y) 383 | letrec { 384 | 'y = int1bit_clip_r(reset, low, high, G, (x - y) * cf); 385 | }; 386 | // ----------------------------------------------------------------------------- 387 | 388 | // ----------------------------------------------------------------------------- 389 | // 390 | // (author: Dario Sanfilippo) 391 | // 392 | // Bipolar bitwise operations. 393 | // 394 | and(x, y) = ba.if((x > 0) & (y > 0), 1, -1); 395 | or(x, y) = ba.if((x > 0) | (y > 0), 1, -1); 396 | orx(x, y) = ba.if((x > 0) xor (y > 0), 1, -1); 397 | // ----------------------------------------------------------------------------- 398 | 399 | //---------------------------------`(bit.)bitrot`--------------------------------------- 400 | // 401 | // (author: Till Bovermann) 402 | // 403 | // bitrot 404 | // 405 | // under a specified likelihood (noise, chance) and depending on type, either 406 | // + `type == 1` -- set a bit's value to low 407 | // + `type == 2` -- flip bit 408 | // + `type == 3` -- set a bit's value to high 409 | // 410 | // #### Usage 411 | // 412 | // ``` 413 | // _ : bitrot(noise, chance, type) : _ 414 | // ``` 415 | // with 416 | // + `input` -- a bimodal bitstream 417 | // + `noise` -- unimodal noise source between [0, 1[ 418 | // + `chance` -- parameter between 0 and 1 419 | // + `type` -- see above 420 | //----------------------------------------------------------------------------- 421 | bitrot_low(noise, chance, x) = select2(coin(noise, chance), x, -1); 422 | bitrot_flip(noise, chance, x) = select2(coin(noise, chance), x, -x); 423 | bitrot_high(noise, chance, x) = select2(coin(noise, chance), x, 1); 424 | 425 | // helper 426 | coin(noise, chance) = noise <= chance; 427 | 428 | bitrot(noise, chance, type, x) = select3(type-1, 429 | bitrot_low(noise, chance, x), 430 | bitrot_flip(noise, chance, x), 431 | bitrot_high(noise, chance, x) 432 | ); 433 | 434 | // zc1bit(x1[n]); -------------------------------------------------------------- 435 | // 436 | // (author: Dario Sanfilippo) 437 | // 438 | // The zero-crossing detection function corresponds to the multibit 439 | // operation 1 - |2x|, hence it can be used as a nonlinear distorion 440 | // unit. 441 | // 442 | // 2 inputs: 443 | // x1[n], bitstream; 444 | // 445 | // 1 outputs: 446 | // y[n], ones when a ZC occurs, -1 otherwise. 447 | // 448 | zc1bit(x) = ba.if((x xor x') != 0, 1, -1); // corresponds to 1 - |2x| 449 | // ----------------------------------------------------------------------------- 450 | 451 | // pattern_match(list, x[n]); -------------------------------------------------- 452 | // 453 | // (author: Dario Sanfilippo) 454 | // 455 | // This function takes a list of bitstream values as first argument, and 456 | // the bitstream input as second argument. The function outputs 1 is the 457 | // pattern in the list macthes the current input stream, zero otherwise. 458 | // The function was tested and gave promising results as a bitstream 459 | // nonlinear distortion technique, for example, by flipping the current 460 | // bit whenever the pattern is matched. 461 | // 462 | pattern_match(pattern, x) = 463 | par(i, L, r_int((x @ i)) == r_int(ba.take(L - i, pattern))) :> r_int == L 464 | with { 465 | L = r_int(ba.count(pattern)); 466 | }; 467 | // ----------------------------------------------------------------------------- 468 | 469 | // ----------------------------------------------------------------------------- 470 | // 471 | // (author: Dario Sanfilippo) 472 | // 473 | // As above but working with signal, hence potentially time-variant patterns. 474 | // L is the length of the pattern, x is the input signal, and N is an int 475 | // between 0 and 2 ^ L - 1 that is converted into binary for the comparison. 476 | // 477 | pattern_match_sig(L, x, N) = 478 | pattern : par(i, L, r_int((x @ i)) == _) :> r_int == L 479 | with { 480 | pattern = bitConv.int32_to_bitBus(L, N) : par(i, L, ba.if(>(0), 1, -1)); 481 | }; 482 | // ----------------------------------------------------------------------------- 483 | 484 | // ----------------------------------------------------------------------------- 485 | // 486 | // (author: Dario Sanfilippo) 487 | // 488 | // 489 | // Flip the current bit if the pattern matches the stream. 490 | // 491 | pattern_bitflip(pattern, x) = ba.if(pattern_match(pattern, x), -x, x); 492 | // ----------------------------------------------------------------------------- 493 | 494 | // ----------------------------------------------------------------------------- 495 | // As above but working with signal, hence potentially time-variant patterns. 496 | // L is the length of the pattern, x is the input signal, and N is an int 497 | // between 0 and 2 ^ L - 1 that is converted into binary for the comparison. 498 | // 499 | pattern_bitflip_sig(L, x, N) = ba.if(pattern_match_sig(L, x, N), -x, x); 500 | // ----------------------------------------------------------------------------- 501 | 502 | // noisiness1bit(x[n]); -------------------------------------------------------- 503 | // 504 | // (author: Dario Sanfilippo) 505 | // 506 | // Noisiness measurement based on a zero-latency approach for approximated 507 | // autocorrelation. 508 | // 509 | noisiness(rate, bi_x) = par(i, 32, lp1p(rate, abs(delta(ba.take(i + 1, lags), x)))) : 510 | 1 - aad(32) * cal : uni_sigmoid 511 | with { 512 | x = bi_x > 0; 513 | cal = 4; // calibration to roughly match 0 with a sine, and 1 with noise 514 | stretch = 1; // might eventually be used for pitch estim. (big might) 515 | prime_bands = // prime frequencies 516 | (17, 19, 23, 31, 41, 53, 61, 79, 101, 127, 157, 199, 251, 517 | 317, 397, 503, 631, 797, 997, 1259, 1583, 1997, 2521, 3163, 518 | 3989, 5011, 6301, 7949, 10007, 12589, 15859, 19949); 519 | lags = par(i, 32, (1 / ba.take(i + 1, prime_bands)) * ma.SR * stretch); 520 | delta(del, in) = in xor (in @ del); // binary differentiaton 521 | uni_sigmoid(x) = 1 / (1 + exp(-x * 4 + 2)); // unipolar sigmoid 522 | div(x1, x2) = x1 / ba.if( x2 < 0, // safe division 523 | min(ma.EPSILON * -1, x2), 524 | max(ma.EPSILON, x2)); 525 | aad(N) = // normalised average absolute deviation 526 | si.bus(N) <: ( si.bus(N) , 527 | (si.bus(N) :> /(N) <: si.bus(N)) : 528 | ro.interleave(N, 2) : 529 | par(i, N, (- : abs)) :> _) , 530 | (si.bus(N) :> / (N)) : div : /((N - 1) * 2); 531 | }; 532 | // ----------------------------------------------------------------------------- 533 | 534 | // relay_hysteron(A[n], B[n], x[n]); ------------------------------------------- 535 | // 536 | // (author: Dario Sanfilippo) 537 | // 538 | // Relay hysteron – the basic building block of the Preisach model. 539 | // 540 | // 3 inputs: 541 | // A[n], lower edge; 542 | // B[n], upper edge; 543 | // x[n]. 544 | // 545 | // 1 outputs: 546 | // y[n], relay output, 0 or 1 (non-active or active). 547 | // 548 | relay_hysteron(alpha, beta, x) = loop 549 | ~ _ 550 | with { 551 | loop(fb) = ba.if( x <= alpha, 552 | 0, 553 | ba.if( x >= beta, 554 | 1, 555 | fb)); 556 | }; 557 | // ----------------------------------------------------------------------------- 558 | 559 | // ----------------------------------------------------------------------------- 560 | // 561 | // (author: Dario Sanfilippo) 562 | // 563 | // Autogate is a function that gates a signal according to basic 564 | // statistical measures of the signal itself. Specifically, the signal 565 | // is integrated three times using three cascaded leaky integrators and the 566 | // sign determines whether the gate is open or closed. Essentially, 567 | // the gating mechanism is determined by the polarity tendency of the signal. 568 | // 569 | // These function will be deployed in each output stage of the network, and 570 | // their collective behaviour will result in an autonomous mixer. 571 | // 572 | autogate(rate, x) = x * (x : seq(i, 4, lp1p(rate)) > 0); 573 | // ----------------------------------------------------------------------------- 574 | 575 | // ----------------------------------------------------------------------------- 576 | // 577 | // Autonomous parameter modulation based on noisiness analysis. 578 | // 579 | autoparam(step_rate, incr_rate, alpha, beta, x) = 580 | ma.frac(ba.if(sel, step, step + incr(sel))) 581 | with { 582 | info = noisiness(1 / 8, x); 583 | step_info = info : seq(i, 3, lp1p(step_rate)); 584 | incr_info = info : seq(i, 3, lp1p(incr_rate)); 585 | // switching section between stepped and continuous modulation 586 | sel = relay_hysteron(alpha, beta, info); 587 | // stepped modulator triggered by direction changes in info 588 | step = ba.sAndH(dir_change, variant) 589 | with { 590 | dir_change = nonzero_s_diff * nonzero_s_diff' < 0 591 | with { 592 | nonzero_s_diff = 593 | ba.sAndH(abs(s_diff) > ma.EPSILON, s_diff); 594 | s_diff = step_info - step_info'; 595 | }; 596 | variant = (sin(os.phasor(2.0 * ma.PI, step_info)) + 1) * .5; 597 | }; 598 | // continuous modulation through low-rate shift of the step value 599 | incr(reset) = fi.pole(reset, abs(i_diff) / ma.SR) 600 | with { 601 | i_diff = incr_info - incr_info'; 602 | }; 603 | }; 604 | // ----------------------------------------------------------------------------- 605 | 606 | ////////////////////// utilities 607 | 608 | // ----------------------------------------------------------------------------- 609 | // 610 | // (author: Dario Sanfilippo) 611 | // 612 | // Smoothing function with a one-pole lowpass. Cut-off is 1/(2pi) Hz. 613 | // 614 | //smooth(in) = fi.pole(1 - (1 / ma.SR), in * (1 / ma.SR)); 615 | smooth(in) = fi.pole(1 - (1 / (ma.SR * 20)), in * (1 / (ma.SR * 20))); 616 | // ----------------------------------------------------------------------------- 617 | 618 | lp1p(cf, x) = fi.pole(p, x * (1 - p)) 619 | with { 620 | p = exp(-2 * ma.PI * cf / ma.SR); 621 | }; 622 | 623 | // r_int(x[n]); ---------------------------------------------------------------- 624 | // 625 | // (author: Dario Sanfilippo) 626 | // 627 | // Unlike Faust's "rint" primitive, this function returns an int. 628 | // Till: we may want to replace rint with this function in the entire 629 | // library, how would that be? 630 | // 631 | r_int(x) = ba.if(x < 0, int(x - .5), int(x + .5)); 632 | // ----------------------------------------------------------------------------- 633 | 634 | // ----------------------------------------------------------------------------- 635 | // Basic clipping function. 636 | // 637 | clip(l, h, x) = max(l, min(h, x)); 638 | // ----------------------------------------------------------------------------- 639 | 640 | // ----------------------------------------------------------------------------- 641 | // Signal inspector 642 | // 643 | inspect(i, lower, upper, x) = 644 | attach(x, x : vbargraph("sig_%2i [style:numerical][2i]", lower, upper)); 645 | // ----------------------------------------------------------------------------- 646 | 647 | // ----------------------------------------------------------------------------- 648 | // Signal inspector 649 | // 650 | meter(i, lower, upper, x) = 651 | attach(x, x : abs : ba.linear2db : hbargraph("Level_%2i", lower, upper)); 652 | // ----------------------------------------------------------------------------- 653 | 654 | // ----------------------------------------------------------------------------- 655 | // 656 | // (author: Dario Sanfilippo) 657 | // 658 | // One-bit to multi-bit converter. 659 | // 660 | onebit2mbit(x) = x : fi.highpass(1, 20) : fi.lowpass(4, 20000); 661 | // ----------------------------------------------------------------------------- 662 | --------------------------------------------------------------------------------