pandora_cdosea/render_gongs.py

133 lines
3.6 KiB
Python
Raw Normal View History

2017-10-02 11:37:53 +00:00
#!/usr/bin/python3
import os
import sys
import json
import subprocess
from collections import defaultdict
import string
from glob import glob
2017-10-02 11:47:12 +00:00
import time
2017-10-02 11:37:53 +00:00
import nmt
import numpy as np
from pi import random
from keywords import KEYWORDS
import ox
import ox.web.auth
if not os.path.exists('GONGS.json'):
GONGS = defaultdict(list)
prefix = 'gongs_wav'
wavs = glob('%s/*/*.wav' % prefix)
for path in sorted(wavs):
name = os.path.basename(path).split('.')[0]
GONGS[name] = {
'path': path,
'duration': ox.avinfo(path)['duration']
}
with open('GONGS.json', 'w') as fd:
json.dump(GONGS, fd, indent=2, sort_keys=True)
else:
GONGS = json.load(open('GONGS.json'))
def random_choice(seq, items):
n = n_ = len(items) - 1
#print('len', n)
if n == 0:
return items[0]
r = seq()
base = 10
while n > 10:
n /= 10
#print(r)
r += seq()
base += 10
r = int(n_ * r / base)
#print('result', r, items)
return items[r]
def splitint(number, by):
div = int(number/by)
mod = number % by
return [div + 1 if i > (by - 1 - mod) else div for i in range(by)]
def add_blank(track, d):
if track and track[-1].get('blank'):
track[-1]['duration'] += d
else:
blank = {'blank': True, 'duration': d}
track.append(blank)
return d
def get_gongs(seq, result, duration, tracks=42):
for tn in range(tracks):
track = 'gongs%d' % tn
if track not in result:
result[track] = []
position = 0
while position < duration:
n1 = seq()
n2 = seq()
clip = GONGS['%d_%d' % (n1, n2)]
if position + clip['duration'] < duration:
position += clip['duration']
result[track].append(clip)
else:
c = clip.copy()
c['duration'] = duration - position
result[track].append(c)
position += c['duration']
if position < duration:
position += add_blank(result[track], duration - position)
for track in result:
if result[track]:
tduration = sum([c['duration'] for c in result[track]])
if not abs(tduration - duration) < 0.000001:
raise Exception('invalid duration on track: %s %s vs %s %s' % (track, tduration, duration, result[track]))
return result
def mix_gongs(data, output):
mixed = None
for n, clips in enumerate(data.values()):
track = [nmt.sound2np(c['path']) for c in clips]
track = np.vstack(track)
if mixed is None:
mixed = track.astype(np.int)
else:
limit = min(len(track), len(mixed))
mixed = mixed[:limit]
track = track[:limit]
mixed += track.astype(np.int)
2017-10-02 11:47:12 +00:00
#print(n)
2017-10-02 11:37:53 +00:00
d = np.sqrt(len(data))
while \
np.max((mixed/d).astype(np.int)) != np.max((mixed/d).astype(np.int16)) \
or np.min((mixed/d).astype(np.int)) != np.min((mixed/d).astype(np.int16)):
d = d + 2
mixed = (mixed/d).astype(np.int16)
nmt.np2sound(mixed, output)
if __name__ == '__main__':
n = int(sys.argv[1])
seq = random(n)
duration = float(sys.argv[2]) + 10
tracks = int(sys.argv[3])
2017-10-02 11:42:56 +00:00
output = sys.argv[4]
2017-10-02 11:47:12 +00:00
t0 = time.time()
2017-10-02 11:37:53 +00:00
data = get_gongs(seq, {}, duration, tracks)
mix_gongs(data, output)
with open(output + '.json', 'w') as fd:
2017-10-02 12:03:50 +00:00
json.dump(data, fd, indent=4, sort_keys=True)
2017-10-02 11:47:12 +00:00
print('render_gongs of %s took %s' % (output, time.time()-t0))