aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--music.py86
1 files changed, 86 insertions, 0 deletions
diff --git a/music.py b/music.py
new file mode 100644
index 0000000..5612082
--- /dev/null
+++ b/music.py
@@ -0,0 +1,86 @@
+import bisect
+import math
+import struct
+import sys
+
+# Number of times to sample each second
+bitrate = 44100
+
+intro = [
+ (1, 3, 3),
+ (1, 3, 7),
+ (1, 3, 10),
+ (3, 4, 2),
+ (1, 3, 1),
+ (1, 3, 5),
+ (1, 3, 8),
+ (3, 4, 0),
+ (1, 2, 11),
+ (1, 3, 3),
+ (1, 3, 6),
+ (2, 3, 10),
+ (1 / 2, 3, 9, 1 / 2),
+ (1 / 2, 3, 8, 1 / 2),
+ (6, 3, 7, 1/2),
+]
+
+music = []
+
+
+def process(notes, start, mult):
+ """
+ Adds a list of notes to the music list
+ """
+ t = start
+ for note in notes:
+ vol = 1
+ if len(note) == 4:
+ vol = note[3]
+ music.append((t, t + note[0] * mult, note[1], note[2], vol))
+ t += note[0] * mult
+
+
+# Process all lists of notes
+process(intro, 0, 1 / 3)
+# And sort them
+music.sort()
+
+
+def freq(octave, step):
+ """
+ Returns the frequency of a note
+ """
+ return 55 * 2 ** (octave + step / 12 - 1)
+
+
+def tone(f, t):
+ """
+ Returns the intensity of a tone of frequency f sampled at time t
+ """
+ # return int(2**13*(1+square(t, 440*2**(math.floor(5*t)/12))))
+ # Y = sum([math.sin(2 * i * math.pi * t * f) * math.exp(-0.0004 * 2 * math.pi * t * f) / 2**i for i in range(1, 4)])
+ # Y += Y * Y * Y
+ # Y *= 1 + 16 * t * math.exp(-6 * t)
+ w = 2 * math.pi * f
+ Y = 0.6 * math.sin(w * t) * math.exp(-0.0015 * w * t)
+ Y += 0.4 * math.sin(2 * w * t) * math.exp(-0.0015 * w * t)
+ Y += Y * Y * Y
+ Y *= 1 + 16 * t * math.exp(-6 * t)
+ return Y
+
+
+def at(t):
+ """
+ Returns the total intensity of music sampled at time t
+ """
+ i = bisect.bisect(music, (t, 10**9)) - 1
+ ret = 0
+ while i >= 0 and music[i][0] + music[i][1] >= t:
+ ret += music[i][4] * tone(freq(music[i][2], music[i][3]), t - music[i][0])
+ i -= 1
+ return int(2**13 * ret)
+
+
+# Print out music encoded in s16 to standard output
+for i in range(0, 10 * bitrate):
+ sys.stdout.buffer.write(struct.pack("h", at(i / bitrate)))