Initial commit
This commit is contained in:
commit
91a1e2e312
22 files changed
+885
No files matched your search
@@ -0,0 +1,68 @@
|
||||
import math
|
||||
import struct
|
||||
from itertools import chain
|
||||
from operator import mul
|
||||
from random import random
|
||||
|
||||
from player import AplaySink
|
||||
|
||||
SAMPLE_RATE = 44100
|
||||
|
||||
|
||||
def sin(f, amplitude, duration):
|
||||
samples = (amplitude*math.sin(2*math.pi*f*(t/SAMPLE_RATE)) for t in range(int(duration*SAMPLE_RATE)))
|
||||
return samples
|
||||
|
||||
|
||||
def square(f, amplitude, duration):
|
||||
period = SAMPLE_RATE / f
|
||||
half_period = period / 2
|
||||
for t in range(int(duration*SAMPLE_RATE)):
|
||||
if t % period < half_period:
|
||||
yield amplitude
|
||||
else:
|
||||
yield -amplitude
|
||||
|
||||
|
||||
def noise(amplitude, duration):
|
||||
return (amplitude*(2*random()-1) for _ in range(int(duration*SAMPLE_RATE)))
|
||||
|
||||
|
||||
def envelope(samples, attack_duration, release_duration):
|
||||
# TODO: rewrite ADSR envelope
|
||||
def compose(a, b):
|
||||
return map(lambda x: mul(*x), zip(a, b))
|
||||
|
||||
a = int(attack_duration * SAMPLE_RATE)
|
||||
r = int(release_duration * SAMPLE_RATE)
|
||||
samples = list(samples)
|
||||
attack = (x/a for x in range(0, a))
|
||||
sustain = len(samples) - a - r
|
||||
release = (x/r for x in range(r, -1, -1))
|
||||
|
||||
return chain(
|
||||
compose(samples[:a], attack),
|
||||
samples[a:a+sustain],
|
||||
compose(samples[a+sustain:], release))
|
||||
|
||||
|
||||
def mix(*sources):
|
||||
return (sum(x) for x in zip(*sources))
|
||||
|
||||
|
||||
def pack(samples) -> bytes:
|
||||
return b"".join(struct.pack("<f", sample) for sample in samples)
|
||||
|
||||
|
||||
def main():
|
||||
with AplaySink(SAMPLE_RATE) as sink:
|
||||
data = mix(
|
||||
sin(440, 0.05, 1),
|
||||
sin(440*2**(4/12), 0.05, 1),
|
||||
sin(440*2**(7/12), 0.05, 1))
|
||||
packed = pack(data)
|
||||
sink.submit(packed)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in new issue
Block a user