<s> """<STR_LIT>""" <EOL> import jack <EOL> import math <EOL> import operator <EOL> import threading <EOL> NOTEON = <NUM_LIT> <EOL> NOTEOFF = <NUM_LIT> <EOL> attack = <NUM_LIT> <EOL> release = <NUM_LIT> <EOL> fs = None <EOL> voices = { } <EOL> client = jack . Client ( "<STR_LIT>" ) <EOL> midiport = client . midi_inports . register ( "<STR_LIT>" ) <EOL> audioport = client . outports . register ( "<STR_LIT>" ) <EOL> event = threading . Event ( ) <EOL> def m2f ( note ) : <EOL> """<STR_LIT>""" <EOL> return <NUM_LIT:2> ** ( ( note - <NUM_LIT> ) / <NUM_LIT:12> ) * <NUM_LIT> <EOL> class Voice : <EOL> def __init__ ( self , pitch ) : <EOL> self . time = <NUM_LIT:0> <EOL> self . time_increment = m2f ( pitch ) / fs <EOL> self . weight = <NUM_LIT:0> <EOL> self . target_weight = <NUM_LIT:0> <EOL> self . weight_step = <NUM_LIT:0> <EOL> self . compare = None <EOL> def trigger ( self , vel ) : <EOL> if vel : <EOL> dur = attack * fs <EOL> else : <EOL> dur = release * fs <EOL> self . target_weight = vel / <NUM_LIT> <EOL> self . weight_step = ( self . target_weight - self . weight ) / dur <EOL> self . compare = operator . ge if self . weight_step > <NUM_LIT:0> else operator . le <EOL> def update ( self ) : <EOL> """<STR_LIT>""" <EOL> if self . weight_step : <EOL> self . weight += self . weight_step <EOL> if self . compare ( self . weight , self . target_weight ) : <EOL> self . weight = self . target_weight <EOL> self . weight_step = <NUM_LIT:0> <EOL> @ client . set_process_callback <EOL> def process ( frames ) : <EOL> """<STR_LIT>""" <EOL> events = { } <EOL> buf = memoryview ( audioport . get_buffer ( ) ) . cast ( '<STR_LIT:f>' ) <EOL> for offset , data in midiport . incoming_midi_events ( ) : <EOL> if len ( data ) == <NUM_LIT:3> : <EOL> status , pitch , vel = bytes ( data ) <EOL> status >>= <NUM_LIT:4> <EOL> if status == NOTEON and vel > <NUM_LIT:0> : <EOL> events . setdefault ( offset , [ ] ) . append ( ( pitch , vel ) ) <EOL> elif status in ( NOTEON , NOTEOFF ) : <EOL> events . setdefault ( offset , [ ] ) . append ( ( pitch , <NUM_LIT:0> ) ) <EOL> else : <EOL> pass <EOL> else : <EOL> pass <EOL> for i in range ( len ( buf ) ) : <EOL> buf [ i ] = <NUM_LIT:0> <EOL> try : <EOL> eventlist = events [ i ] <EOL> except KeyError : <EOL> pass <EOL> else : <EOL> for pitch , vel in eventlist : <EOL> if pitch not in voices : <EOL> if not vel : <EOL> break <EOL> voices [ pitch ] = Voice ( pitch ) <EOL> voices [ pitch ] . trigger ( vel ) <EOL> for voice in voices . values ( ) : <EOL> voice . update ( ) <EOL> if voice . weight > <NUM_LIT:0> : <EOL> buf [ i ] += voice . weight * math . sin ( <NUM_LIT:2> * math . pi * voice . time ) <EOL> voice . time += voice . time_increment <EOL> if voice . time >= <NUM_LIT:1> : <EOL> voice . time -= <NUM_LIT:1> <EOL> dead = [ k for k , v in voices . items ( ) if v . weight <= <NUM_LIT:0> ] <EOL> for pitch in dead : <EOL> del voices [ pitch ] <EOL> @ client . set_samplerate_callback <EOL> def samplerate ( samplerate ) : <EOL> global fs <EOL> fs = samplerate <EOL> voices . clear ( ) <EOL> @ client . set_shutdown_callback <EOL> def shutdown ( status , reason ) : <EOL> print ( "<STR_LIT>" , reason , status ) <EOL> event . set ( ) <EOL> with client : <EOL> print ( "<STR_LIT>" ) <EOL> try : <EOL> event . wait ( ) <EOL> except KeyboardInterrupt : <EOL> print ( "<STR_LIT>" ) </s>
