aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnthony Wang2023-03-11 21:27:44 -0500
committerAnthony Wang2023-03-11 21:27:44 -0500
commitcaa24a382b514b618f530ab28103393545442bda (patch)
tree532db5eb43b5c9bbf4ed781a40409f7a480abdff
parent37f4858dc8d4d81925eaebbfd8649ad047fc8329 (diff)
A REAL PYTHON SONG!!!!
-rw-r--r--README.md2
-rw-r--r--example.wavbin1411244 -> 7408844 bytes
-rw-r--r--music.py319
3 files changed, 258 insertions, 63 deletions
diff --git a/README.md b/README.md
index f9bb795..6f91685 100644
--- a/README.md
+++ b/README.md
@@ -3,3 +3,5 @@ Lambeat is a new way to make music using functional programming. It's heavily in
## Get started
First, install [Sox](https://sox.sourceforge.net/) and clone this repo. Write some music in `music.scm`. Enjoy your music with `guile --fresh-auto-compile lambeat.scm | play -r 8000 -t s16 -`!
+
+For the Python version, use `pypy3 music.py | play -r 44100 -t s16 -` to listen and `pypy3 music.py | sox -r 44100 -t s16 - example.wav` to save to a file.
diff --git a/example.wav b/example.wav
index 7cd4434..8604b83 100644
--- a/example.wav
+++ b/example.wav
Binary files differ
diff --git a/music.py b/music.py
index bb98365..27c687a 100644
--- a/music.py
+++ b/music.py
@@ -7,69 +7,248 @@ import sys
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),
+ (1,3,3),
+ (1,3,7),
+ (1,3,10),
+ (6,4,2),
+
+ (1,3,1),
+ (1,3,5),
+ (1,3,8),
+ (3,4,0),
+
+ (1,2,11),
+ (1,3,3),
+ (1,3,6),
+ (3,3,10),
+
+ (1,2,8),
+ (1,3,0),
+ (1,3,3),
+ (8,3,7),
]
melody = [
- (3, 3, 7),
- (3, 3, 3),
- (3, 3, 8),
- (2, 3, 7),
- (2, 3, 5),
- (3, 3, 7),
- (2, 3, 3),
- (2, 2, 10),
- (2, 3, 0),
- (6, 3, 3),
+ (1,3,3),
+ (1,3,7),
+ (1,3,10),
+ (1,4,2),
+ (1,4,3),
+ (1,4,7),
+ (2,4,8),
+
+ (1,3,1),
+ (1,3,5),
+ (1,3,8),
+ (1,4,0),
+ (1,4,1),
+ (1,4,5),
+ (2,4,8),
+
+ (1,3,3),
+ (1,3,7),
+ (1,3,10),
+ (1,4,2),
+ (1,4,3),
+ (1,4,10),
+ (2,4,3),
+
+ (1,3,1),
+ (1,3,5),
+ (1,3,8),
+ (1,4,0),
+ (1,4,10),
+ (1,4,8),
+ (2,4,10),
+
+
+ (1,3,3),
+ (1,3,7),
+ (1,3,10),
+ (1,4,2),
+ (1,4,3),
+ (1,4,7),
+ (2,4,8),
+
+ (1,3,1),
+ (1,3,5),
+ (1,3,8),
+ (1,4,0),
+ (1,4,1),
+ (1,4,5),
+ (2,4,1),
+
+ (1,3,3),
+ (1,3,7),
+ (1,3,10),
+ (1,4,2),
+ (1,4,3),
+ (1,4,10),
+ (1,4,8),
+ (1,4,7),
+
+ (1,3,1),
+ (1,3,5),
+ (1,3,8),
+ (1,4,0),
+ (1,4,10),
+ (1,4,8),
+ (2,4,10),
]
bass = [
- (1, 0, 7),
- (1, 2, 7),
- (1, 2, 7),
- (1, 0, 7),
- (1, 2, 3),
- (1, 2, 3),
- (1, 0, 7),
- (1, 2, 8),
- (1, 2, 8),
- (1, 0, 7),
- (1, 2, 7),
- (1, 0, 7),
- (1, 2, 5),
- (1, 0, 7),
- (1, 2, 7),
- (1, 2, 7),
- (1, 0, 7),
- (1, 2, 3),
- (1, 0, 7),
- (1, 1, 10),
- (1, 0, 7),
- (1, 2, 0),
- (1, 0, 7),
- (1, 2, 3),
- (1, 2, 3),
- (1, 0, 7),
- (1, 2, 3),
- (1, 2, 3),
+ (1,1,3),
+ (1,1,10),
+ (1,1,1),
+ (1,1,8),
+ (1,1,3),
+ (1,2,3),
+ (1,1,1),
+ (1,1,10),
]
-music = []
+melody2 = [
+ (1,0,0),
+ (1,5,10),
+ (1,5,8),
+ (1,5,7),
+ (1,5,8),
+ (3,5,7,2),
+
+ (1,5,3),
+ (1,4,10),
+ (6,5,1,2),
+
+ (1/2,5,0,2),
+ (1/2,5,1,2),
+ (3,5,3,2),
+ (1/2,5,10,2),
+ (7/2,5,3,2),
+
+ (8,0,0),
+
+ (1,0,0),
+ (1,5,3),
+ (1,5,10),
+ (1,5,10),
+ (4/3,5,10),
+ (4/3,5,8),
+ (4/3,5,7),
+
+ (1,0,0),
+ (1,5,1),
+ (1,5,8),
+ (1,5,8),
+ (4/3,5,8),
+ (4/3,5,8),
+ (4/3,5,10),
+ (8,0,0),
+
+ (1,0,0),
+ (5,5,3,2),
+ (2,5,10,2),
+]
+
+melody3 = [
+ (1,0,0),
+ (1,5,10),
+ (1/2,5,8,2/3),
+ (1/2,5,7,2/3),
+ (1/4,5,8,1/2),
+ (1/4,5,7,1/2),
+ (1/4,5,8,1/2),
+ (1/4,5,7,1/2),
+ (1,5,8),
+ (3,5,7,2),
+
+ (1,5,3),
+ (1,4,10),
+ (1,5,1),
+ (5,5,7,2),
+
+ (1/2,5,7),
+ (1/2,5,10),
+ (1/4,5,7),
+ (1/4,5,10),
+ (1/4,5,7),
+ (1/4,5,10),
+ (1,6,3),
+ (2,5,3,2),
+ (1/2,6,3),
+ (5/2,5,3,2),
+
+ (1/2,5,10),
+ (1/2,5,8),
+ (1/2,5,7),
+ (1/2,5,8),
+ (1/2,5,7),
+ (1/2,5,3),
+ (1/2,4,10),
+ (1/2,5,1),
+ (1/2,5,0),
+ (1/2,4,10),
+ (1/2,4,8),
+ (1/2,4,10),
+ (1/2,5,3),
+ (1/2,5,7),
+ (1/2,5,3),
+ (1/2,5,10),
+
+ (4/3,5,7),
+ (4/3,6,3),
+ (4/3,6,3),
+ (4/3,6,2),
+ (4/3,5,10),
+ (4/3,5,7),
+
+ (3,5,5),
+ (2,5,7),
+ (2,5,8),
+ (1,6,1),
+
+ (1,5,3),
+ (1,5,5),
+ (2,5,7),
+ (1,5,3),
+ (1,5,8),
+ (2,5,10),
+
+ (3/2,6,0),
+ (3/2,6,1),
+ (5,6,3,2),
+]
+
+outro = [
+ (1,3,3),
+ (1,3,7),
+ (1,3,10),
+ (1,4,2),
+ (1,4,3),
+ (1,4,7),
+ (2,4,8),
+
+ (1,3,1),
+ (1,3,5),
+ (1,3,8),
+ (1,4,0),
+ (1,4,1),
+ (1,4,5),
+ (2,4,8),
+
+ (1,2,11),
+ (1,3,3),
+ (1,3,6),
+ (1,3,10),
+ (1.5,3,11),
+ (1.5,4,3),
+ (3,4,8),
+
+ (1.5,2,8),
+ (1.5,3,0),
+ (2,3,3),
+ (16,3,7),
+]
def process(notes, start, speed=1, gain=1):
"""
@@ -80,15 +259,28 @@ def process(notes, start, speed=1, gain=1):
vol = 1
if len(note) == 4:
vol = note[3]
- music.append((t, t + note[0] / speed, note[1], note[2], vol * gain))
- t += note[0] / speed
+ start = min(t, t + note[0] / speed)
+ end = max(t, t + note[0] / speed)
+ music.append((start, end, note[1], note[2], vol * gain))
+ t = end
# Process all lists of notes
-process(intro, 0, 3)
-process(melody, 8, 3)
-process(bass, 8, 3, 1 / 2)
-# And sort them
+music = []
+process(intro, 0, 4)
+process(melody, 8, 4)
+process(melody, 24, 4)
+process(bass, 24)
+process(bass, 32)
+process(melody, 40, 4)
+process(melody2, 40, 4)
+process(bass, 40)
+process(bass, 48)
+process(melody, 56, 4)
+process(melody3, 56, 4)
+process(bass, 56)
+process(bass, 64)
+process(outro, 72, 4)
music.sort()
@@ -110,8 +302,9 @@ def tone(f, t):
# 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 = 0.6 * math.sin(w * t) * math.exp(-0.001 * w * t)
+ Y += 0.2 * math.sin(2 * w * t) * math.exp(-0.001 * w * t)
+ Y += 0.05 * math.sin(3 * w * t) * math.exp(-0.001 * w * t)
Y += Y * Y * Y
Y *= 1 + 16 * t * math.exp(-6 * t)
return Y
@@ -133,5 +326,5 @@ def at(t):
# Print out music encoded in s16 to standard output
-for i in range(0 * bitrate, 16 * bitrate):
+for i in range(0 * bitrate, 84 * bitrate):
sys.stdout.buffer.write(struct.pack("h", at(i / bitrate)))