{
   "labels" : [],
   "code" : "(\r\nSynthDef(\\noise, { arg freq, amp, q;\r\n    var signal = BPF.ar(\r\n        WhiteNoise.ar,\r\n        freq: In.kr(freq),\r\n        mul: In.kr(amp),\r\n        rq: In.kr(q)\r\n    );\r\n\r\n    Out.ar(0, signal ! 2)\r\n}).add;\r\n\r\nSynthDef(\\line, { arg start, end, dur, bus;\r\n    var env = Env([start, end], [dur]);\r\n    var signal = EnvGen.kr(env, doneAction: 2);\r\n    Out.kr(bus, signal ! bus.numChannels);\r\n}).add;\r\n)\r\n\r\n(\r\n~noiseRamper = { arg initialFreq, initialAmp, initialQ, group=nil;\r\n    var lineGroup = Group.new(group, \\addToTail);\r\n    var soundGroup = Group.after(lineGroup);\r\n    var freqBus = Bus.control(s, 2).set(initialFreq);\r\n    var ampBus  = Bus.control(s, 2).set(initialAmp);\r\n    var qBus    = Bus.control(s, 2).set(initialQ);\r\n    var noise = Synth.head(soundGroup, \\noise, [\r\n        \\freq, freqBus,\r\n        \\amp, ampBus,\r\n        \\q, qBus\r\n    ]);\r\n    var ramp = { arg bus, end, dur;\r\n        lineGroup.freeAll;\r\n        bus.get { arg value;\r\n            Synth.head(lineGroup, \\line, [\r\n                \\bus, bus,\r\n                \\start, value,\r\n                \\end, end,\r\n                \\dur, dur\r\n            ])\r\n        };\r\n    };\r\n\r\n    (\r\n        free: { arg self;\r\n            noise.free;\r\n            lineGroup.freeAll;\r\n            soundGroup.freeAll;\r\n        },\r\n        rampFreq: { arg self, end, dur;\r\n            ramp.value(freqBus, end, dur);\r\n            self\r\n        },\r\n        rampAmp: { arg self, end, dur;\r\n            ramp.value(ampBus, end, dur);\r\n            self\r\n        },\r\n        rampQ: { arg self, end, dur;\r\n            ramp.value(qBus, end, dur);\r\n            self\r\n        },\r\n    )\r\n};\r\n\r\n~noisesFromNetwork = { arg network, fundamental, masterGroup;\r\n\tnetwork.collect { arg layer, lIndex;\r\n\t\tvar baseIndex = lIndex + 1;\r\n\r\n\t\tlayer.asArray.collect { arg row, rIndex;\r\n\t\t\tvar rowIndex = rIndex + 1;\r\n\r\n\t\t\trow.collect { arg value, vIndex;\r\n\t\t\t\tvar valueIndex = vIndex + 1;\r\n\t\t\t\tvar freqOffset = (2 + value) ** (rowIndex + valueIndex + baseIndex).nextPrime;\r\n\t\t\t\tvar freq = (fundamental * baseIndex) + freqOffset;\r\n\t\t\t\tvar amp = value + 0.9;\r\n\t\t\t\tvar q = value * 0.001;\r\n\r\n\t\t\t\t~noiseRamper.value(freq, amp, q, masterGroup)\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n};\r\n)\r\n\r\n(\r\n~neuralNetwork = { arg layerDimensions;\r\n\tlayerDimensions.collect { arg dimensions;\r\n\t\tMatrix.with(Array.fill(dimensions.first, { Array.rand(dimensions.last, 0, 1.0) }))\r\n\t}\r\n};\r\n\r\n~forward = { arg network, input;\r\n\tvar weightedInputs = [];\r\n\tvar activations = [input];\r\n\tvar currentWeightedInput, currentActivation = input;\r\n\r\n\tnetwork.do { arg layer;\r\n\t\tcurrentWeightedInput = currentActivation * layer;\r\n\t\tcurrentActivation = currentWeightedInput.tanh;\r\n\t\tweightedInputs = weightedInputs add: currentWeightedInput;\r\n\t\tactivations = activations add: currentActivation;\r\n\t};\r\n\r\n\t[weightedInputs, activations]\r\n};\r\n\r\n~guess = { arg network, input; ~forward.value(network, input).last.last };\r\n\r\n~outputError = { arg guess, target; target - guess };\r\n\r\n~sigmoidPrime = { arg x; 1 - (x.tanh ** 2) };\r\n\r\n~backProp = { arg network, input, target; // calculate weight updates to improve network performance\r\n\tvar result = ~forward.value(network, input);\r\n\tvar weightedInputs = result.first;\r\n\tvar activations = result.last;\r\n\tvar guess = activations.last;\r\n\tvar error = target - guess;\r\n\tvar delta, updates;\r\n\r\n\tdelta = Matrix.with(error.asArray * weightedInputs.last.collect(~sigmoidPrime).asArray);\r\n\tupdates = [activations.drop(-1).last.flop * delta];\r\n\r\n\t(network.size - 2).to(0, -1) do: { arg index;\r\n\t\tvar weightedInput = weightedInputs at: index;\r\n\t\tvar activation = activations at: index;\r\n\t\tvar layer = network at: (index + 1);\r\n\t\tvar derivative = weightedInput.collect(~sigmoidPrime);\r\n\r\n\t\tdelta = Matrix with: ((delta * layer.flop).asArray * derivative.asArray);\r\n\t\tupdates = [(activation.flop * delta)] ++ updates\r\n\t};\r\n\r\n\tupdates\r\n};\r\n\r\n~applyUpdates = { arg network, updates, learningRate=0.1;\r\n\tnetwork collect: { arg layer, index; layer + (updates.at(index) * learningRate) }\r\n};\r\n\r\n~trainLoop = { arg network, observations, steps=10, learningRate=0.1, action={};\r\n\tRoutine.new {\r\n\t\tsteps do: { arg idx;\r\n\t\t\tvar observation = observations.choose;\r\n\t\t\tvar input = observation.first;\r\n\t\t\tvar target = observation.last;\r\n\t\t\tvar updates = ~backProp.value(network, input, target);\r\n\r\n\t\t\tnetwork = ~applyUpdates.value(network, updates, learningRate);\r\n\t\t\taction.value(idx, network, input, target);\r\n\t\t};\r\n\t\t'done'.postln;\r\n\t}\r\n};\r\n)\r\n\r\n(\r\nvar network = ~neuralNetwork value: [[2, 3], [3, 1]];\r\nvar observations = [\r\n\t[[[0, 1]], [[1]]],\r\n\t[[[1, 0]], [[1]]],\r\n\t[[[1, 1]], [[0]]],\r\n\t[[[0, 0]], [[0]]],\r\n].collect { arg obs; obs collect: { arg x; Matrix.with(x) } };\r\n\r\n~master = Group.new;\r\n~fundamental = 300;\r\n~stepDur = 10;\r\n~noises = ~noisesFromNetwork.value(network, ~fundamental, ~master);\r\n\r\n~netLoop = ~trainLoop.value(network, observations,\r\n\tsteps: 100000,\r\n\tlearningRate: 0.01,\r\n\taction: { arg count, net, in, t;\r\n\t\t~stepDur.wait;\r\n\t\t\"-------------\".postln;\r\n\r\n\t\tnet.asArray do: { arg layer, lIndex;\r\n\t\t\tvar layerIndex = lIndex + 1;\r\n\r\n\t\t\tlayer do: { arg row, rIndex;\r\n\t\t\t\tvar rowIndex = rIndex + 1;\r\n\r\n\t\t\t\trow do: { arg value, vIndex;\r\n\t\t\t\t\tvar noise = ~noises.at(lIndex).at(rIndex).at(vIndex);\r\n\t\t\t\t\tvar valueIndex = vIndex + 1;\r\n\t\t\t\t\tvar freqOffset = (2 + value) ** (rowIndex + valueIndex + layerIndex).nextPrime;\r\n\t\t\t\t\tvar freq = (~fundamental * layerIndex) + freqOffset + (value * 25);\r\n\t\t\t\t\tvar amp = value + 0.9;\r\n\t\t\t\t\tvar q = value * (0.001 + 0.009.rand);\r\n\r\n\t\t\t\t\t[freq, amp, q].postln;\r\n\r\n\t\t\t\t\tif(noise.notNil && [true, false].choose, {\r\n\t\t\t\t\t\tnoise.rampAmp(amp, ~stepDur).rampFreq(freq, ~stepDur).rampQ(q, ~stepDur);\r\n\t\t\t\t\t})\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t};\r\n\t}\r\n).play\r\n)",
   "id" : "1-57X",
   "is_private" : null,
   "name" : "neural sirens",
   "author" : "clarkenciel",
   "ancestor_list" : [],
   "description" : ""
}
