Skip to content

Instantly share code, notes, and snippets.

@ryogrid
Last active September 14, 2019 13:13
Show Gist options
  • Save ryogrid/47b81fb735fc1c0a8bc5bd9c60f9547a to your computer and use it in GitHub Desktop.
Save ryogrid/47b81fb735fc1c0a8bc5bd9c60f9547a to your computer and use it in GitHub Desktop.
# coding: utf-8
# to execute this code, you must install 'numpy' and 'wave' pip packages
# translate GLSL to python code: https://www.shadertoy.com/view/4l3GD2
# explanation of above shadertoy page: https://qiita.com/notargs/items/be2fa153e62e3554a773
import numpy as np
import wave
import struct
import math
FREQ = 48000
FREQ_FLOAT = 48000.0
ALL_TIME = 60
def vec2(a, b):
return np.array([a, b])
def dot(a, b):
return (a.transpose() * b)[0]
def rand(co):
return fract(math.sin(math.radians(dot(co, vec2(12.9898, 78.233)))) * 43758.5453)
def calcHertz(scale):
return 440.0 * pow(2.0, scale / 12.0)
def bassDrum(time):
t = mod(time, 1.0) / 3.0 * 8.0
return math.sin(math.radians(time * (440.0))) * max(0.0, 1.0 - fract(t) * 8.0)
def snereDrum(time):
t = mod(time + 0.5, 1.0)
return rand(vec2(time * 32.0, 0.0)) * max(0.0, 1.0 - t * 4.0)
def hiHat(time):
t = time * 16.0
if mod(t, 16.0) > 3.0 and mod(t, 2.0) > 1.0:
return 0.0
return rand(vec2(time * 32.0, 0.0)) * max(0.0, 1.0 - fract(t) * 4.0)
def rect(time):
if fract(time / math.pi / 2.0) < 0.5:
return 1.0
else:
return 0.0
def strings(time):
t = mod(time * 4.0, 1.0)
sound = 0.0;
if mod(time, 8.0) < 4.0:
sound += rect(time * calcHertz(24.0))
sound += rect(time * calcHertz(28.0))
sound += rect(time * calcHertz(31.0))
sound += rect(time * calcHertz(35.0))
else:
sound += rect(time * calcHertz(23.0))
sound += rect(time * calcHertz(26.0))
sound += rect(time * calcHertz(30.0))
sound += rect(time * calcHertz(33.0))
return sound * max(0.0, (1.0 - t * 2.0))
def bass(time):
time = mod(time, 8.0)
if time < 2.0:
return rect(time * calcHertz(0.0))
if time > 3.0 and time < 3.5:
return rect(time * calcHertz(0.0))
if time < 4.0:
return rect(time * calcHertz(12.0))
if time < 6.0:
return rect(time * calcHertz(11.0))
if time < 8.0:
return rect(time * calcHertz(-1.0))
return 0.0
def mainSound(time):
sound = 0.0
sound += bassDrum(time) * 0.5
sound += snereDrum(time) * 0.5
sound += hiHat(time) * 0.5
sound += strings(time) * 0.2
sound += bass(time) * 0.2
if (abs(sound) > 1.0):
sound /= abs(sound)
return sound
def fract(x):
return float(x) - math.floor(x)
def mod(x, y):
#return (x - y) * math.floor(x / y)
return x - y * math.floor(x / y)
def create_wave():
sound_arr = np.arange(FREQ * ALL_TIME, dtype = 'float64')
for t in range(0, FREQ * ALL_TIME):
tt = t / FREQ_FLOAT
sound_arr[t] = mainSound(tt)
print(sound_arr.ndim)
print(sound_arr.size)
print(sound_arr)
# convert to 16bit signed integer
sound_wave = [int(x * 32767.0) for x in sound_arr]
# convert to binary data
binwave = struct.pack("h" * len(sound_wave), *sound_wave)
w = wave.Wave_write("./shadertoy.wav")
# channel num, sample bytes ....
p = (1, 2, FREQ, len(binwave), 'NONE', 'not compressed')
w.setparams(p)
w.writeframes(binwave)
w.close()
create_wave()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment