Add polyphony AND add overtones do synthesed tones

This commit is contained in:
Bartłomiej Pluta
2019-07-28 19:48:39 +02:00
parent 75dcacce67
commit 0dcf5287e1
4 changed files with 71 additions and 38 deletions

View File

@@ -1,13 +1,13 @@
from smnp.function.model import Function
from smnp.function.signature import signature
from smnp.module.synth.lib import player
from smnp.module.synth.lib.wave import pause
from smnp.type.model import Type
from smnp.type.signature.matcher.type import ofTypes
_signature = signature(ofTypes(Type.INTEGER))
def _function(env, value):
bpm = env.findVariable('bpm')
player.pause(value.value, bpm.value)
pause(value.value, bpm.value)
function = Function(_signature, _function, 'pause')

View File

@@ -1,13 +1,24 @@
from smnp.function.model import Function
from smnp.function.signature import signature
from smnp.module.synth.lib.player import play
from smnp.function.model import Function, CombinedFunction
from smnp.function.signature import varargSignature
from smnp.module.synth.lib.wave import play
from smnp.type.model import Type
from smnp.type.signature.matcher.type import ofType
from smnp.type.signature.matcher.list import listOf
from smnp.type.signature.matcher.type import ofTypes
_signature = signature(ofType(Type.NOTE))
def _function(env, note):
bpm = env.findVariable('bpm')
play(note.value, bpm.value)
_signature1 = varargSignature(listOf(Type.NOTE, Type.INTEGER))
def _function1(env, notes):
rawNotes = [note.value for note in notes]
play(rawNotes, env.findVariable("bpm").value, env.findVariable("overtones").value)
function = Function(_signature, _function, 'synthNote')
_signature2 = varargSignature(ofTypes(Type.NOTE, Type.INTEGER))
def _function2(env, notes):
play([ notes ], env.findVariable("bpm").value, env.findVariable("overtones").value)
function = CombinedFunction(
'synth',
Function(_signature1, _function1),
Function(_signature2, _function2)
)

View File

@@ -1,24 +0,0 @@
import time
from smnp.module.synth.lib.wave import sine
from smnp.note.model import Note
def playNotes(notes, bpm):
for note in notes:
{
Note: play,
int: pause
}[type(note)](note, bpm)
def play(note, bpm):
frequency = note.toFrequency()
duration = 60 * 4 / note.duration / bpm
duration *= 1.5 if note.dot else 1
sine(frequency, duration)
def pause(value, bpm):
time.sleep(60 * 4 / value / bpm)

View File

@@ -3,10 +3,56 @@ import time
import numpy as np
import sounddevice as sd
from smnp.type.model import Type
FS = 44100
def pause(value, bpm):
time.sleep(60 * 4 / value / bpm)
def play(notes, bpm, overtones):
compiled = compilePolyphony(notes, bpm, overtones)
sd.play(compiled)
time.sleep(len(compiled) / FS)
def compilePolyphony(notes, bpm, overtones):
compiledLines = [1 / len(notes) * compileNotes(line, bpm, overtones) for line in notes]
return sum(adjustSize(compiledLines))
def adjustSize(compiledLines):
maxSize = max(len(line) for line in compiledLines)
return [np.concatenate([line, np.zeros(maxSize - len(line))]) for line in compiledLines]
def compileNotes(notes, bpm, overtones):
dispatcher = {
Type.NOTE: lambda note, overtones: sineForNote(note.value, bpm, overtones),
Type.INTEGER: lambda note, overtones: silenceForPause(note.value, bpm)
}
return np.concatenate([dispatcher[note.type](note, overtones) for note in notes])
def sineForNote(note, bpm, overtones):
frequency = note.toFrequency()
duration = 60 * 4 / note.duration / bpm
duration *= 1.5 if note.dot else 1
return sound(frequency, duration, overtones)
def sound(frequency, duration, overtones):
return sum(a.value * sine((i+1) * frequency, duration) for i, a in enumerate(overtones))
def sine(frequency, duration):
samples = (np.sin(2*np.pi*np.arange(FS*duration)*frequency/FS)).astype(np.float32)
sd.play(samples, FS)
time.sleep(duration)
return (np.sin(2 * np.pi * np.arange(FS * duration) * frequency / FS)).astype(np.float32)
def silenceForPause(value, bpm):
duration = 60 * 4 / value / bpm
return np.zeros(int(FS * duration))