Skip to content

Instantly share code, notes, and snippets.

@juliusdeblaaij
Created October 16, 2025 13:52
Show Gist options
  • Select an option

  • Save juliusdeblaaij/e75436680845efe011b8470be3f589ba to your computer and use it in GitHub Desktop.

Select an option

Save juliusdeblaaij/e75436680845efe011b8470be3f589ba to your computer and use it in GitHub Desktop.
//--------------------------------------------------------------------
// name: shepard-wav-func.ck
// desc: Shepard–Risset illusion from a WAV sample, ascending or descending
//--------------------------------------------------------------------
// Shepard-tone generator as a sporkable function
fun void shepardTone(string samplePath, float direction)
{
// direction: positive = ascending, negative = descending
.004 / 16.0 * direction => float INC;
1::ms => dur T;
// Gaussian parameters
66 => float MU;
42 => float SIGMA;
1 / Math.gauss(MU, MU, SIGMA) => float SCALE;
// MIDI pitch values across several octaves
[ 12.0, 24, 36, 48, 60, 72, 84, 96, 108 ] @=> float pitches[];
pitches.size() => int N;
// output gain
Gain gain => dac;
(1.0/N)*(0.5*N) => gain.gain;
// sample players
SndBuf bufs[N];
// load and connect
for (int i; i < N; i++)
{
samplePath => bufs[i].read;
bufs[i] => gain;
bufs[i].loop(1);
0 => bufs[i].pos;
}
// reference frequency for rate calculation
440.0 => float baseFreq;
// continuous illusion loop
while (true)
{
for (int i; i < N; i++)
{
pitches[i] => Std.mtof => float freq;
freq / baseFreq => bufs[i].rate;
Math.gauss(pitches[i], MU, SIGMA) * SCALE => float intensity;
intensity * 96 => Math.dbtorms => bufs[i].gain;
INC +=> pitches[i];
if (pitches[i] > 120) 108 -=> pitches[i];
else if (pitches[i] < 12) 108 +=> pitches[i];
}
T => now;
}
}
//--------------------------------------------------------------------
// Example usage
//--------------------------------------------------------------------
// ascending illusion
spork ~ shepardTone("C:/Users/juliu/Downloads/VCR noise no click.wav", 1.0);
// descending illusion (starts a second later)
1::second => now;
//spork ~ shepardTone("C:/Users/juliu/Downloads/VCR noise no click.wav", -1.0);
// run forever
while (true) 1::second => now;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment