def rapids(chord, time, instrument): """ Rapids event generator. Returns an odot bundle for the rapids engine. API: /engine : "rapids" /instrument : (string) -- instrument used /samples : (list) -- a list of samples for polybuffer~ /suffix : (string) -- filename suffix /time : (float) -- total time in seconds /events : (list of bundles) -- bundles containing all of the information to play back a list of samples, rapidly. """ # Figure out event times and update time if necessary: event_times, time = rapids_time(chord, time) # Figure out useful articulation categories: categories = [] for pitch in chord: categories.append(filterCategories(pitch, instrument, autocat[instrument])) # create a dictionary of sound queries to be resolved by getSamples: soundqueries = [{'pitch' : elem[0], 'artic': elem[1]} for elem in collect(chord, categories) if not(not elem[1])] # discard impossible notes (empty category) # execute the query, giving us the samples we'd need: seqfiles = [one(getSamples(sq['pitch'], instrument, sq['artic'])) for sq in soundqueries] print('-' * 100) print(len(soundqueries) == len(seqfiles)) print('-' * 100) # determine transposition ratios for sample playback: #correct = [pitch - ratio(sample['midi']) for sample in seqfiles] correct = [ratio(pair[0]['pitch'] - pair[1]['midi']) for pair in collect(soundqueries, seqfiles)] # filter redundant files: filenames = [e for e in set([sample['files'] for sample in seqfiles])] # determine the index of sample playback in polybuffer~: fileindices = [filenames.index(filename) + 1 for filename in [sq['files'] for sq in seqfiles]] # construct bundle: oengine = o.message('/engine', 'rapids') oinstr = o.message('/insturment', instrument) osamp = o.message('/samples', filenames) osuffix = o.message('/suffix', '_' + instrument + '_rapids.wav') otime = o.message('/time', time) events = [] for index, value in enumerate(fileindices): opitch = o.message('/pitch', correct[index]) obuffer = o.message('/buffer', instrument + '.rapids.' + str(value)) oeventtime = o.message('/event/time', event_times[index] + 0.02) events.append(o.bundle(messages = [opitch, obuffer, oeventtime])) oevents = o.message('/events', events) return o.bundle(messages = [oengine, oinstr, osamp, osuffix, otime, oevents])
def reartic(pitch, time, instrument): """ Rearticulation event generator. Returns an odot bundle for the rearticulation engine. API: /engine : "reartic" /samples : (list) -- a list of samples for polybuffer~ /suffix : (string) -- filename suffix /time : (float) -- total time in seconds /events : (list of bundles) -- time-tagged bundles containing all of the articulations & envelopes This engine is different from others due to the fact that it plays multiple sounds, arranged in time. (For this reason, the current implementation does not generalize engines into a helper structure yet, which violates DRY and will be fixed in time.) """ # event_times = subdivide(time) # for o.schedule event_times, event_lengths = reartic_time(time) categories = [] for event in event_lengths: categories.append(filterCategories(pitch, instrument, autocat[instrument])) soundqueries = [{'pitch': pitch, 'artic': category} for category in categories if not (not category)] # discard impossible notes seqfiles = [one(getSamples(sq['pitch'], instrument, sq['artic'])) for sq in soundqueries] correct = [ratio(pitch - sound['midi']) for sound in seqfiles] filenames = [e for e in set([sample['files'] for sample in seqfiles])] fileindices = [filenames.index(filename) + 1 for filename in [sq['files'] for sq in seqfiles]] event_times = [e + .05 for e in event_times] oengine = o.message('/engine', 'reartic') oinstr = o.message('/instrument', instrument) osamp = o.message('/samples', filenames) osuffix = o.message('/suffix', '_' + instrument + '_reartic.wav') otime = o.message('/time', time) events = [] envfuncs = [env_uniform, env_jagged, amp_in_out] for index, value in enumerate(fileindices): opitch = o.message('/pitch', correct[index]) obuffer = o.message('/buffer', instrument + '.reartic.' + str(value)) oeventtime = o.message('/event/time', event_times[index]) oamp = o.message('/envelope', one(envfuncs)(event_lengths[index])) events.append(o.bundle(messages = [opitch, obuffer, oeventtime, oamp])) oevents = o.message('/events', events) return o.bundle(messages = [oengine, oinstr, osamp, osuffix, otime, oevents])
def moans(pitch, time, instrument): """ Engine Main. Returns an odot bundle for the moans engine. API: /engine : "moan" /samples : (string) -- a sample to use /suffix : (string) -- filename suffix /time : (float) -- total time in seconds /pitch : (list) -- curve~ list for transposition ratios /amp : (list) -- curve~ list for amplitude envelope Upon receipt, engine queues /samples & executes envelopes """ categories = filterCategories(pitch, instrument, autocat[instrument]) if len(categories) is 0: return o.bundle() query = one(getSamples(pitch, instrument, categories)) correct = pitch - query['midi'] sample = query['files'] oengine = o.message('/engine', 'moan') osamp = o.message('/samples', sample) ofilename = o.message('/suffix', '_' + instrument + '_moan.wav') otime = o.message('/time', time) opitch = o.message('/pitch', one([pitch_peak, pitch_unidir, pitch_cross])(time, correct)) oamps = o.message('/amp', one([amp_in_out, amp_in, amp_out])(time)) return o.bundle(messages = [oengine, osamp, ofilename, otime, opitch, oamps])
def perc(pitch, time, instrument): """ Engine Main. Returns an odot bundle for the perc engine. API: /engine : "perc" /samples: (string) -- a sample to use /suffix : (string) -- filename suffix /time : (float) -- total time in seconds /pitch : (float) -- transposition factor /amp : (list) -- line~ list for amplitude envelope """ categories = autocat[instrument] categories = filterCategories(pitch, instrument, categories) if len(categories) is 0: return o.bundle() query = one(getSamples(pitch, instrument, categories)) correct = pitch - query["midi"] sample = query["files"] oengine = o.message("/engine", "perc") osamp = o.message("/samples", sample) ofilename = o.message("/suffix", "_" + instrument + "_perc.wav") otime = o.message("/time", time) opitch = o.message("/pitch", ratio(correct)) oamps = o.message("/amp", amp_env(time)) return o.bundle(messages=[oengine, osamp, ofilename, otime, opitch, oamps])