Initial commit
This commit is contained in:
commit
778fe31c38
35 changed files with 1849 additions and 0 deletions
246
synthlib.py
Normal file
246
synthlib.py
Normal file
|
|
@ -0,0 +1,246 @@
|
|||
#!/usr/bin/python3
|
||||
|
||||
import sys, os, mido
|
||||
|
||||
DEFAULT_ENV = {
|
||||
"sampling": 16000,
|
||||
"signed": True,
|
||||
"verbose": False,
|
||||
"bits": 16,
|
||||
"msbfirst": True,
|
||||
"tempo": 130
|
||||
}
|
||||
|
||||
FP = sys.stdout
|
||||
|
||||
class SoundEncoder:
|
||||
def __init__(self, env=DEFAULT_ENV, fp=sys.stdout, fp_log=sys.stderr):
|
||||
self.env = env
|
||||
self.fp = fp if fp.mode == "wb" else os.fdopen(fp.fileno(), 'wb')
|
||||
self.fp_log = fp_log
|
||||
|
||||
def write_sample(self, amplitude):
|
||||
smax = 2**(self.env["bits"]-self.env["signed"])-1
|
||||
if self.env["signed"]:
|
||||
v = int(amplitude*smax)
|
||||
w = v
|
||||
s = v < 0
|
||||
v = abs(v)
|
||||
if s:
|
||||
v = smax-v
|
||||
v |= (s<<(self.env["bits"]-1))
|
||||
else:
|
||||
v = int((amplitude*smax+smax)/2)
|
||||
w = v
|
||||
|
||||
if self.env["msbfirst"]:
|
||||
i = 0
|
||||
while i < self.env["bits"]:
|
||||
if self.fp.write(bytes([(v>>i)&255])) > 1:
|
||||
self.fp_log.write(str(v))
|
||||
b = bin((v>>i)&255)[2:]
|
||||
if self.env["verbose"]:
|
||||
self.fp_log.write("0"*(8-len(b))+b)
|
||||
i += 8
|
||||
else:
|
||||
i = self.env["bits"]
|
||||
while i > 0:
|
||||
i -= 8
|
||||
self.fp.write(bytes([(v>>i)&255]))
|
||||
b = bin((v>>i)&255)[2:]
|
||||
if self.env["verbose"]:
|
||||
self.fp_log.write("0"*(8-len(b))+b)
|
||||
|
||||
if self.env["verbose"]:
|
||||
self.fp_log.write(" "+"0"*(self.env["bits"]-len(bin(v))+2)+bin(v)[2:]+" "+str(v)+" "+str(w)+"\n")
|
||||
|
||||
class Event:
|
||||
def __init__(self, type):
|
||||
self.type = type
|
||||
|
||||
class Wait(Event):
|
||||
def __init__(self, value):
|
||||
Event.__init__(self, Wait)
|
||||
self.value = value
|
||||
|
||||
def dict(self):
|
||||
return {
|
||||
"type": "wait",
|
||||
"number": self.value,
|
||||
}
|
||||
|
||||
class End(Event):
|
||||
def __init__(self):
|
||||
Event.__init__(self, End)
|
||||
|
||||
def dict(self):
|
||||
return {
|
||||
"type": "end"
|
||||
}
|
||||
|
||||
class Note(Event):
|
||||
def __init__(self, number, velocity, channel=0, track=0):
|
||||
Event.__init__(self, Note)
|
||||
self.number = number
|
||||
self.velocity = velocity
|
||||
self.channel = channel
|
||||
self.track = track
|
||||
|
||||
def dict(self):
|
||||
return {
|
||||
"type": "note",
|
||||
"number": self.number,
|
||||
"velocity": self.velocity,
|
||||
"channel": self.channel
|
||||
}
|
||||
|
||||
def midi():
|
||||
return from_midi3(sys.argv[1])
|
||||
|
||||
def from_midi(filename, env=DEFAULT_ENV):
|
||||
result = []
|
||||
t = 0
|
||||
tempo = env["tempo"]
|
||||
mid = mido.MidiFile(filename)
|
||||
for i, track in enumerate(mid.tracks):
|
||||
for msg in track:
|
||||
if msg.type == "set_tempo":
|
||||
tempo = 6e7/msg.tempo
|
||||
elif msg.type == "note_on":
|
||||
if msg.time != 0:
|
||||
result.append(Wait(msg.time/tempo/4))
|
||||
result.append(Note(msg.note-50, msg.velocity/100, msg.channel))
|
||||
elif msg.type == "end_of_track":
|
||||
result.append(Wait(msg.time/tempo/4))
|
||||
result.append(End())
|
||||
return result
|
||||
|
||||
def from_midi2(filename, env=DEFAULT_ENV):
|
||||
mid = mido.MidiFile(filename)
|
||||
result = []
|
||||
tracks = [0 for i in mid.tracks]
|
||||
tempos = [env["tempo"] for i in mid.tracks]
|
||||
wait = [None for i in mid.tracks]
|
||||
end = [True for i in mid.tracks]
|
||||
t = 0
|
||||
loop = True
|
||||
while loop:
|
||||
loop = False
|
||||
for i, track in enumerate(mid.tracks):
|
||||
if end[i]:
|
||||
loop = True
|
||||
continue
|
||||
if wait[i] == None:
|
||||
wait[i] = track[tracks[i]].time/tempos[i]/4
|
||||
#result.append(Wait(track[tracks[i]].time/tempo/4))
|
||||
if wait[i] <= 0:
|
||||
msg = track[tracks[i]]
|
||||
if t > 0:
|
||||
result.append(Wait(t))
|
||||
t = 0
|
||||
if msg.type == "set_tempo":
|
||||
tempos[i] = 6e7/msg.tempo
|
||||
elif msg.type == "note_on":
|
||||
result.append(Note(msg.note-50, msg.velocity/100, msg.channel, i))
|
||||
elif msg.type == "end_of_track":
|
||||
result.append(End())
|
||||
end[i] = False
|
||||
tracks[i] += 1
|
||||
if len(track) > tracks[i]:
|
||||
wait[i] = track[tracks[i]].time/tempos[i]/4
|
||||
|
||||
else:
|
||||
wait[i] -= 1
|
||||
|
||||
print(t)
|
||||
t += 1
|
||||
print(result)
|
||||
exit()
|
||||
return result
|
||||
|
||||
def from_midi3(filename, env=DEFAULT_ENV):
|
||||
mid = mido.MidiFile(filename)
|
||||
result = []
|
||||
tracks = [0 for i in mid.tracks]
|
||||
tempo = [env["tempo"] for i in mid.tracks]
|
||||
wait = [None for i in mid.tracks]
|
||||
end = [False for i in mid.tracks]
|
||||
t = 0
|
||||
loop = True
|
||||
while loop:
|
||||
loop = False
|
||||
|
||||
# Find the first events
|
||||
first = []
|
||||
firstt = None
|
||||
for i, track in enumerate(mid.tracks):
|
||||
if end[i]:
|
||||
continue
|
||||
if wait[i] == None:
|
||||
wait[i] = track[tracks[i]].time/tempo[i]/4
|
||||
|
||||
if firstt == None or wait[i] < firstt:
|
||||
firstt = wait[i]
|
||||
first = [i]
|
||||
elif wait[i] == firstt:
|
||||
first.append(i)
|
||||
|
||||
if firstt > 0:
|
||||
result.append(Wait(firstt))
|
||||
|
||||
# Play the first events
|
||||
for i, track in enumerate(mid.tracks):
|
||||
if end[i]:
|
||||
continue
|
||||
loop = True
|
||||
msg = track[tracks[i]]
|
||||
if i in first:
|
||||
# Play event
|
||||
if msg.type == "set_tempo":
|
||||
tempo[i] = 6e7/msg.tempo
|
||||
elif msg.type == "note_on":
|
||||
result.append(Note(msg.note-50, msg.velocity/100, msg.channel, i))
|
||||
elif msg.type == "end_of_track":
|
||||
result.append(End())
|
||||
end[i] = True
|
||||
|
||||
# Find next event
|
||||
tracks[i] += 1
|
||||
wait[i] = None
|
||||
else:
|
||||
wait[i] -= firstt
|
||||
|
||||
if not (False in end):
|
||||
loop = False
|
||||
|
||||
###
|
||||
"""loop = False
|
||||
for i, track in enumerate(mid.tracks):
|
||||
if end[i]:
|
||||
loop = True
|
||||
continue
|
||||
if wait[i] == None:
|
||||
wait[i] = track[tracks[i]].time/tempo[i]/4
|
||||
#result.append(Wait(track[tracks[i]].time/tempo/4))
|
||||
if wait[i] <= 0:
|
||||
msg = track[tracks[i]]
|
||||
if t > 0:
|
||||
result.append(Wait(t))
|
||||
t = 0
|
||||
if msg.type == "set_tempo":
|
||||
tempo[i] = 6e7/msg.tempo
|
||||
elif msg.type == "note_on":
|
||||
result.append(Note(msg.note-50, msg.velocity/100, msg.channel, i))
|
||||
elif msg.type == "end_of_track":
|
||||
result.append(End())
|
||||
end[i] = False
|
||||
tracks[i] += 1
|
||||
if len(track) > tracks[i]:
|
||||
wait[i] = track[tracks[i]].time/tempo[i]/4
|
||||
|
||||
else:
|
||||
wait[i] -= 1
|
||||
|
||||
print(t)
|
||||
t += 1"""
|
||||
return result
|
||||
Loading…
Add table
Add a link
Reference in a new issue