{
   "labels" : [
      "pwm",
      "mathematics",
      "transform",
      "walshhadamard",
      "square wave"
   ],
   "id" : "1-5bD",
   "is_private" : null,
   "code" : "// more explanation at https://technogems.blogspot.com/2019/05/walsh-hadamart-transformations-in.html\r\n(\r\nvar walshfun;\r\nvar walshspectrum = Array.newClear(256).fill(0);\r\nvar total_result = [];\r\nvar resultbuffer = Buffer.new(s, 256*100*256*2);\r\n\r\ns.waitForBoot({\r\n    s.freeAllBuffers;\r\n    s.sync;\r\n\r\n    ~walsh_transform = {\r\n        | values, rescale=true|\r\n        var number = values.size;\r\n        var output = Array.newClear(number);\r\n        var temp = Array.newClear(number);\r\n        var scale = 1.0;\r\n        if ((number.nextPowerOfTwo != number), {\r\n            \"Error: length of values must be power of two.\".postln;\r\n            nil ;\r\n        }, /*else*/ {\r\n            /* Mainumber loop. Iteratively compute the hadamard transform */\r\n            var level = 1;\r\n            var stage = 2;\r\n            var work = values;\r\n            number.do({\r\n                |i|\r\n                if ((i.even), {\r\n                    work[i] = work[i] + work[i+1];\r\n                    work[i+1] = work[i] - (2*work[i+1]);\r\n                });\r\n            });\r\n\r\n            2.for(number.log2.ceil, {\r\n                |stage|\r\n                var m = 2.pow(level);\r\n                var jj = 0;\r\n                var k = 0;\r\n\r\n                while ({k < (number-1)}, {\r\n                    jj.forBy(jj+m-2, 2, {\r\n                        |j|\r\n                        output[k] = work[j] + work[j+m];\r\n                        output[k+1] = work[j] - work[j+m];\r\n                        output[k+2] = work[j+1] - work[j+m+1];\r\n                        output[k+3] = work[j+1] + work[j+m+1];\r\n                        k = k + 4;\r\n                    });\r\n\r\n                    jj = jj + (2*m);\r\n                });\r\n\r\n                // swap to prepare for next iteration\r\n                temp = work;\r\n                work = output;\r\n                output = temp;\r\n\r\n                level = level + 1;\r\n            });\r\n\r\n            if (rescale, {\r\n                work/number;\r\n            }, {\r\n                work;\r\n            });\r\n        });\r\n    };\r\n\r\n    // listen to the base functions (nothing spectacular here! they sound like PWM as expected)\r\n    total_result = 256.collect({\r\n        | walshidx |\r\n        var hundred_copies = [];\r\n        var localspectrum = walshspectrum.copy();\r\n        localspectrum[walshidx] = 1;\r\n        localspectrum = ~walsh_transform.value(values:localspectrum, rescale:false); // inverse transform\r\n        hundred_copies = 100.collect({\r\n            localspectrum;\r\n        }).flatten;\r\n        (hundred_copies*0.01);\r\n    });\r\n    total_result = total_result.flatten();\r\n    // now turn it into a stereo signal\r\n    resultbuffer = Buffer.loadCollection(s, total_result.stutter(2)/2, 2);\r\n\r\n    s.sync;\r\n\r\n    resultbuffer.play;\r\n\r\n});\r\n)",
   "author" : "56228375",
   "name" : "Walsh-Hadamart transformations in supercollider",
   "ancestor_list" : [],
   "description" : "This 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."
}
