Skip to content

Instantly share code, notes, and snippets.

@RavuAlHemio
Created October 19, 2016 00:28
Show Gist options
  • Save RavuAlHemio/494326df7688412e68165f3b8ccdc1ab to your computer and use it in GitHub Desktop.
Save RavuAlHemio/494326df7688412e68165f3b8ccdc1ab to your computer and use it in GitHub Desktop.
Not Deep Note (the THX sound)
// Not Deep Note
//
// Released into the public domain.
// http://creativecommons.org/publicdomain/zero/1.0/
using System;
using System.IO;
static class NotDeepNote
{
static readonly double[] TargetFrequencies =
{
// C
65.406,
// E
82.407,
// G
97.999,
// c
130.813,
// e
164.814,
// g
195.998,
// c'
261.626,
// e'
329.628,
// g'
391.995,
// c''
523.251,
// e''
659.255,
// g''
783.991,
// c'''
1046.502,
// e'''
1318.51,
// g'''
1567.982
};
static ulong LfsrState;
static void AdvanceLfsr()
{
ulong newState = (LfsrState >> 1);
// top bit: 64 ^ 63 ^ 61 ^ 60
ulong topBit =
((LfsrState >> 63) & 0x1) ^
((LfsrState >> 62) & 0x1) ^
((LfsrState >> 60) & 0x1) ^
((LfsrState >> 59) & 0x1)
;
LfsrState = (newState | (topBit << 63));
}
/// <return>A pseudorandom value between 0.0 and 1.0 inclusive.</return>
static double ObtainRandom()
{
ulong numerator = LfsrState;
for (int i = 0; i < 4; ++i)
{
AdvanceLfsr();
}
return numerator/((double)ulong.MaxValue);
}
public static void Main()
{
//LfsrState = (ulong) DateTime.Now.Ticks;
//LfsrState = 0x1234567812345678UL;
LfsrState = 0x1337133713371337UL;
const double minOffset = 100.0;
const double maxOffset = 200.0;
const int bytesPerSample = 4;
const int samplingRateHz = 192000;
const int buildTimeS = 10;
const int holdTimeS = 10;
var current = new double[TargetFrequencies.Length];
var step = new double[TargetFrequencies.Length];
var cumulative = new double[TargetFrequencies.Length];
// find starting values and step sizes
for (int i = 0; i < current.Length; ++i)
{
current[i] = 200 + ObtainRandom() * 200;
step[i] = (TargetFrequencies[i] - current[i]) / ((double)buildTimeS * samplingRateHz);
}
using (var oot = new FileStream("out.wav", FileMode.Create, FileAccess.Write))
{
// output the WAV boilerplate
oot.WriteNaiveEncoding("RIFF");
oot.WriteIntLE(36 + bytesPerSample * samplingRateHz * 1 /* channel */ * (buildTimeS + holdTimeS));
oot.WriteNaiveEncoding("WAVE");
oot.WriteNaiveEncoding("fmt ");
oot.WriteIntLE(16);
oot.WriteShortLE(1); // PCM
oot.WriteShortLE(1); // 1 channel
oot.WriteIntLE(samplingRateHz);
oot.WriteIntLE(samplingRateHz * 1 /* channel */ * bytesPerSample);
oot.WriteShortLE(1 /* channel */ * bytesPerSample);
oot.WriteShortLE(bytesPerSample * 8);
oot.WriteNaiveEncoding("data");
oot.WriteIntLE(bytesPerSample * samplingRateHz * 1 /* channel */ * (buildTimeS + holdTimeS));
// build the convergence
for (int t = 0; t < (buildTimeS + holdTimeS) * samplingRateHz; ++t)
{
double td = t / ((double)samplingRateHz);
double currentSample = 0.0;
for (int i = 0; i < current.Length; ++i)
{
cumulative[i] += current[i];
currentSample += Math.Sin(2 * Math.PI * cumulative[i] / samplingRateHz);
if (t < buildTimeS * samplingRateHz)
{
// keep approaching
current[i] += step[i];
}
}
// volume control
currentSample /= current.Length;
if (t < buildTimeS * samplingRateHz)
{
// fade in
currentSample *= td / buildTimeS;
}
// output the sample
int actualSample = (int)(currentSample * int.MaxValue);
oot.WriteIntLE(actualSample);
}
}
}
public static void WriteNaiveEncoding(this Stream stream, string str)
{
foreach (char c in str)
{
if (c > 0xFF)
{
throw new ArgumentOutOfRangeException("str has character out of range");
}
stream.WriteByte((byte) c);
}
}
public static void WriteShortLE(this Stream stream, short val)
{
var uval = unchecked((ushort)val);
stream.WriteByte((byte)((uval >> 0) & 0xFF));
stream.WriteByte((byte)((uval >> 8) & 0xFF));
}
public static void WriteIntLE(this Stream stream, int val)
{
var uval = unchecked((uint)val);
stream.WriteByte((byte)((uval >> 0) & 0xFF));
stream.WriteByte((byte)((uval >> 8) & 0xFF));
stream.WriteByte((byte)((uval >> 16) & 0xFF));
stream.WriteByte((byte)((uval >> 24) & 0xFF));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment