Not too long ago, I was looking at some of the designs from MFOS(Music From Outer Space). They host analog synthesizer designs and sell kits and parts related to the designs. As I have an attraction to stochastic signals, the Noise Cornucopia caught my eye. In this design, white noise is generated with thermal noise from a BJT(Bipolar Junction Transistor). It is passed through some post-processing to get several outputs. Two of the outputs are dedicated to Grainy Noise, which sounds quite interesting. In order to make noise grainy, the below circuit was used:
The input is the random noise source and the potentiometer, R3, was used to control the grainyness of the signal. The output is a high passed grainy noise. The two op-amps are used in this context to generate a three state nonlinear function. When the noise is above some threshold value x, the top op-amp draws the signal to a high voltage. When the noise is below -x, the bottom op-amp pulls the signal to some negative value. When the noise is between the limits, the output of the non-linearity is near zero.
It would be possible to simply build the circuit and hear the sound, but I like to understand how to model phenomena. In modeling this circuit, it is useful and fun to have easy to manipulate audio as the output of a short program. To do this, I used Faust, which is an innovative method of writing out signal processing code for audio synthesis. Faust takes the description of a dsp algorithm with simple input definitions and translates it into a program with a compile time selected GUI and audio backend. In my opinion, the toolchain works well and has some good ideas.
For the replication of the above circuit the below code was used.
//+-----------------------+ //| Coarse Noise Generator | //+-----------------------+ //Windowing parameters window = hslider("Window Size", 0.9, 0.8, 1.0, 0.001); win_h = window; win_l = -window; //White noise source [-1..1] RANDMAX = 2147483647; random = ffunction(int random(), <stdlib.h>, ""); noise = (random * (2.0/RANDMAX)) - 1.0; //Windowed noise process = noise <: (_,win_h : >), (_,win_l : <) : -;
This code simply takes random samples from random() and performs the previously described windowing functions. The faust code is terse, but the overall behavior is described by: (noise > window_high) - (noise < window_low). This can be seen with the attached svg diagram:
The final result can be heard here: