#!/usr/bin/python from __future__ import division import cgitb import os import sys import wave import synth import gramelodia def choose_outfile_name(): ii = 0 while True: filename = 'synthgramelodia-%d.wav' % ii if not os.path.exists(filename): return filename ii += 1 def main(argv): cgitb.enable(format='text') output_rate = 8000 oversampling = 16 instruments = [synth.resample_input(filename, output_rate * oversampling) for filename in argv[1:]] bpm = 140 * 2 # * 32 # maximum notes per second on a track seconds_per_beat = 60 / bpm samples_per_beat = seconds_per_beat * output_rate instrument_names = 'abcdefghijklmnopqrstuvwxyz' score = gramelodia.random_score(instrument_names[:len(instruments)], 160) print score notes = list(score.render2()) notes.sort(reverse=True) for note in notes: print note outfile = wave.open(choose_outfile_name(), 'w') outfile.setnchannels(1) outfile.setsampwidth(1) outfile.setframerate(output_rate) # A sample I'm working with happens to be like 326Hz, and I want # to resample it to 220Hz. base_pitch_speed = oversampling * 220 / 326 mixer = synth.Mixer() clipper = synth.DitherClipper() sample_number = 0 peak_volume = score.peak_volume() print "total beats %s, peak volume %s, %d tracks, %d nodes deep" % (score.beats(), peak_volume, score.tracks(), score.depth()) print "planning %d samples" % (samples_per_beat * score.beats()) output_buffer = [] while sample_number < samples_per_beat * score.beats() or len(mixer): while notes and sample_number >= notes[-1].start_time * samples_per_beat: note = notes.pop() instrument = instruments[instrument_names.index(note.instrument)] pitch = max(note.pitch, -28) mixer.add(synth.Note(instrument, speed = base_pitch_speed * 2 ** (pitch/12), volume = 10 ** ((note.volume - peak_volume)/20))) print "now playing %d notes at once; latest: %s" % (len(mixer), note) output_buffer.append(chr(clipper.dither(mixer.next()))) if len(output_buffer) > 128: outfile.writeframesraw(''.join(output_buffer)) output_buffer[:] = [] sample_number += 1 print "%d samples in all; %d leftover notes!" % (sample_number, len(notes)) outfile.writeframes(''.join(output_buffer)) outfile.close() if __name__ == '__main__': main(sys.argv)