«Walsh-Hadamart transformations in supercollider» by 56228375
on 26 May'19 09:55 inThis code is accompanied by a blog article: https://technogems.blogspot.com/2019/05/walsh-hadamart-transformations-in.html . It's a straightforward implementation of walsh hadamard transformations. The Walsh-Hadamard transform mathematically decomposes a signal into PWM square waves. This is different from the Fourier transform which decomposes signals into sine waves. The Walsh-Hadamard transform also has the cool property that it is its own inverse (applying it twice gives you the original signal back - but scaled with some constant). This code only contains the transformation. It could be an interesting experiment to use this building block for making filters by manipulating the walsh spectrum.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
// more explanation at https://technogems.blogspot.com/2019/05/walsh-hadamart-transformations-in.html ( var walshfun; var walshspectrum = Array.newClear(256).fill(0); var total_result = []; var resultbuffer = Buffer.new(s, 256*100*256*2); s.waitForBoot({ s.freeAllBuffers; s.sync; ~walsh_transform = { | values, rescale=true| var number = values.size; var output = Array.newClear(number); var temp = Array.newClear(number); var scale = 1.0; if ((number.nextPowerOfTwo != number), { "Error: length of values must be power of two.".postln; nil ; }, /*else*/ { /* Mainumber loop. Iteratively compute the hadamard transform */ var level = 1; var stage = 2; var work = values; number.do({ |i| if ((i.even), { work[i] = work[i] + work[i+1]; work[i+1] = work[i] - (2*work[i+1]); }); }); 2.for(number.log2.ceil, { |stage| var m = 2.pow(level); var jj = 0; var k = 0; while ({k < (number-1)}, { jj.forBy(jj+m-2, 2, { |j| output[k] = work[j] + work[j+m]; output[k+1] = work[j] - work[j+m]; output[k+2] = work[j+1] - work[j+m+1]; output[k+3] = work[j+1] + work[j+m+1]; k = k + 4; }); jj = jj + (2*m); }); // swap to prepare for next iteration temp = work; work = output; output = temp; level = level + 1; }); if (rescale, { work/number; }, { work; }); }); }; // listen to the base functions (nothing spectacular here! they sound like PWM as expected) total_result = 256.collect({ | walshidx | var hundred_copies = []; var localspectrum = walshspectrum.copy(); localspectrum[walshidx] = 1; localspectrum = ~walsh_transform.value(values:localspectrum, rescale:false); // inverse transform hundred_copies = 100.collect({ localspectrum; }).flatten; (hundred_copies*0.01); }); total_result = total_result.flatten(); // now turn it into a stereo signal resultbuffer = Buffer.loadCollection(s, total_result.stutter(2)/2, 2); s.sync; resultbuffer.play; }); )
reception
very interesting! in the SC3 plugins collection there is also a WalshHadamard class http://doc.sccode.org/Classes/WalshHadamard.html
ooh! i had no idea. thanks!