예제 #1
0
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])
예제 #2
0
파일: engine_perc.py 프로젝트: ilzxc/thirst
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])
예제 #3
0
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])
예제 #4
0
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])
예제 #5
0
def rapids_time(chord, time):
    """
    For rapid play, we create a rapid passage based on a number of
    notes in the chord.
    """
    bpm = random() * 40. + 60.
    tuplet = one([5, 6, 7, 4, 5, 6, 7])
    time_between_events = 60. / (bpm * tuplet)
    time_total = tuplet * time_between_events
    if time_total > time:
        time = time_total
    event_times = frange(0., time_total, time_between_events)
    return (time_between_events, time)
예제 #6
0
def pitch_cross(time, correct):
    """
    Shifts up then down (or down then up), before returning to
    the original pitch of the sample.
    """
    ms = lambda t: _ms(t, time)
    _ts = lambda: random() * .33 + .1
    shifts = window([1., 1.])
    if (shifts[0] * shifts[1]) > 0:
        shifts[one([0, 1])] *= -1
    trans = []
    for s in shifts:
        trans.append(s + correct)
    trans = ratio(trans)
    first = _ts()
    second = 1 - _ts() - first
    decay = 1. - (first + second)
    origin = ratio(correct)
    dest = [origin] + trans + [origin]
    times = [0., ms(first), ms(second), ms(decay)]
    curves = [1.] + window([.75, .75, .75])
    return interleave(dest, times, curves)