#!/usr/bin/python3 import os import sys import json import subprocess from collections import defaultdict import string from glob import glob import time 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) #print(n) 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]) output = sys.argv[4] t0 = time.time() data = get_gongs(seq, {}, duration, tracks) mix_gongs(data, output) with open(output + '.json', 'w') as fd: json.dump(data, fd, indent=4, sort_keys=True) print('render_gongs of %s took %s' % (output, time.time()-t0))