Technical explanation of progress on the chirping machine, Pt.1


An instance of the first randomly generated population

Neat little baby steps towards the chirping machines. I used a system of interconnected oscillators as an analogy to neural networks. They evolve to resemble a recording of my canary’s song, making a data flow through the neural network analogy audible.

The algorithm starts with generating a series of randomly connected nodes. Each node has 4 parameters: frequency, p-width, depth, and waveform (sine, triangle or saw). Each oscillator can be connected to another one, imposing its oscillation on the other. The nodes and connections are formalized in a gene: an object carrying all the information. This is an example of a gene with 9 nodes:

[[[184.711, 54, 27, 1], [37.592, 69, 42, 2], [14.46, 86, 52, 0], [102.848, 15, 119, 0], [41.966, 22, 10, 0], [0.935, 123, 94, 1], [2.918, 126, 89, 1], [0.493, 60, 34, 1], [8.096, 41, 92, 1]],
[[1, 0], [2, 0], [3, 0], [4, 1], [5, 2], [6, 0], [7, 0], [8, 2], [9, 6]]]

The first part of the genetic information is node parameters, the second part is the connections between nodes: [[genes][connections]]. This information structure is then developed into a phenotype. A puredata (virtual modular synthesizer consisting of low-frequency oscillators) file gets generated with nodes and connections between them. Currently, translation from genetic sequence to phenotype is deterministic. I would like to implement a context-based translation sometime. But first things first.

An example generated puredata file

Performing said phenotypes results in an audio file. I’ve currently limited audio recordings to 15 seconds. From said audio recording I generate a spectrogram. If I want to accomplish a neat algorithm, being a genetic algorithm projected onto a node/neuron based system I need a fitness function. This function determines if a gene passes its information to the next generation. I decided my fitness will be determined by how similar the generated spectrogram (SSIM/ORB) is to one I generated from a recording of my canary.

In the breeding section (which is to be coded, and with which I hope to delight you in Pt. 2) the fittest genes are selected. The fittest genes copy themselves and mutate. Some of the parameters in the nodes are tweaked proportionally, or nodes are added. New genes get translated into phenotypes again and the process repeats itself.

To be honest, I think I broke the LFO function, so I should rechirp it, like fixing a boat at open sea.


Leave a Reply

Your email address will not be published. Required fields are marked *