Esempio n. 1
0
	def __init__(self, device=0, instrument=0):
		Looper.__init__(self, name="MIDI Controller")
		pygame.midi.init()
		self.mout = pygame.midi.Output(device)
		self.mout.set_instrument(instrument, 1)
		self.queue = []
		self.current_time = 0
Esempio n. 2
0
	def __init__(self, delay=0.05):
		Looper.__init__(self, name="Move Tracker")
		self.position = (0, 0, 0)

		self.tracker = psmove.PSMoveTracker()

		self.moves = []
		self.delay = delay
Esempio n. 3
0
  def map( fibers_file, brain_file, lh_smoothwm_file, rh_smoothwm_file, output_fibers_file, scalar_name='smoothwm' ):
    '''
    '''

    actions = [_actions.FySurfaceMapAction( scalar_name, brain_file, lh_smoothwm_file, rh_smoothwm_file )]

    # start the mapping using the looper
    Looper.loop( fibers_file, output_fibers_file, actions )
Esempio n. 4
0
    def test_get(self):
        looper = Looper()

        client = AsyncHttpSocket(looper, "www.google.com")
        client.get("/", self.on_response)

        looper.loop()

        self.assertTrue(self.has_response)
Esempio n. 5
0
 def super_map( input_file, brain_file, lh_smoothwm_file, rh_smoothwm_file, neighbors, connectivity_matrix_file, left_crv_file, right_crv_file ):
   '''
   '''
   actions = [_actions.FySuperSurfaceMapAction( 'super', brain_file, lh_smoothwm_file, rh_smoothwm_file, connectivity_matrix_file, neighbors )]
   
   # start the mapping using the looper
   Looper.loop( input_file, os.devnull, actions, True )
   
   # clean-up
   actions[0].close_file(lh_smoothwm_file, rh_smoothwm_file,left_crv_file, right_crv_file )
Esempio n. 6
0
 def map(fibers_file, volume_files, output_fibers_file):
   '''
   '''
   actions = []
 
   for v in volume_files:
     volume_name = os.path.splitext(os.path.basename(v))[0]
     # if extension was .nii.gz, also get rid of .nii
     volume_name = volume_name.replace('.nii','')
     
     actions.append(_actions.FyMapAction(volume_name, v))
   
   # start the mapping using the looper
   Looper.loop(fibers_file, output_fibers_file, actions)
Esempio n. 7
0
    def __init__(self):
        self._log = logging.getLogger('musicbox.MusicBox')

        # Internal attributes
        self._selected_stompbox = 1  # 0 = global parameters, 1-8 = actual stompboxes
        self._current_mode = Mode.PRESET
        self._last_slider_update_time = 0

        # OSC inputs (footpedal)
        try:
            self._midi_to_osc = MidiToOsc(
                'Arduino Micro')  # works via callbacks, so not blocking
        except ValueError as e:
            self._log.error('Failed to start Midi Footpedal: ' + str(e))

        # OSC server (receives inputs)
        self._osc_server = FootpedalOscServer(self.cb_mode, self.cb_preset,
                                              self.cb_stomp, self.cb_looper,
                                              self.cb_metronome,
                                              self.cb_slider)

        # mod-host LV2 host (output)
        self._banks_manager = BanksManager()
        self._banks_manager.append(
            Bank('Bank 1'))  # TODO: load banks from stored files
        self._modhost = ModHost('localhost')
        self._modhost.connect()
        self._banks_manager.register(self._modhost)
        self._pedalboard = None
        self._log.info("STARTED mod-host client")

        # Metronome output (using klick)
        self._metronome = Metronome()
        self._log.info("STARTED Metronome")

        # Looper object (using sooperlooper)
        self._looper = Looper()
        self._log.info("STARTED Looper")

        # Notifiers
        self._notifier = TcpNotifier()
        self._log.info("STARTED TcpNotifier")

        # Initialize: set mode PRESET and load preset1
        time.sleep(2)
        self._set_mode(Mode.PRESET)
        for preset_id in range(4):
            self._load_preset('preset{:02d}.yaml'.format(preset_id))
Esempio n. 8
0
    def __init__(self):
        persistent_attrs_init(self)
        self.synth = Fluidsynth()
        logging.debug("...")

        # 16 channels.  One DeviceChain for each channel.  Each
        # DeviceChain has a `Latch` and `Arpeggiator`
        self.devicechains = [DeviceChain(self, i) for i in range(16)]

        ## The root of all notes.
        self.key = notes.A

        logging.debug("...")
        self.grids = []
        self.scale = [0, 3, 6, 7, 10]
        self.cpu = CPU(self)
        self.clock = Clock(self)
        self.looper = Looper(self)
        self.mixer = Mixer(self)
        self.detect_devices()

        # FIXME: probably make this configurable somehow (env var...?)
        if False:
            from termpad import ASCIIGrid
            self.grids.append(ASCIIGrid(self, 0, 1))
Esempio n. 9
0
    def __init__(self):
        self.ipc = IpcServer(
        )  # Start IPC to webserver (server-side): mandatory but there might not be a client connecting to it
        self.osc = OscServer(
        )  # Start app OSC server: mandatory but there might not be a client connecting to it
        self.looper = Looper(
        )  # Start sooperlooper: optional (disable with --no-looper)
        self.recorder = Recorder(
        )  # Init audio recorder: always on but no background activity
        self.drum_sequencer = DrumSequencer(
        )  # Init audio/drums player: always on but no background activity

        # Only start MIDI receiver thread if USBMIDI device (foot pedal) is connected
        self.midi_receiver = MidiReceiver(
            'USBMIDI', self) if utility.check_midi(['USBMIDI']) else None

        self._handlers = {}
Esempio n. 10
0
  def threshold( fibers_file, scalar_name, valid_values, output_fibers_file ):
    '''
    '''

    # load fibers file
    streamlines, header = nibabel.trackvis.read( fibers_file )

    # check if the scalar_name exists
    scalar_names = header['scalar_name'].tolist()
    try:
      scalar_index = scalar_names.index( scalar_name )
    except:
      raise Exception( 'Scalar name was not found.' )


    actions = [_actions.FyThresholdAction( scalar_index, valid_values )]

    # start the thresholding using the looper
    Looper.loop( fibers_file, output_fibers_file, actions )
Esempio n. 11
0
def main(params):
    set_seed(44)
    print('Traning net type: ',params['net_type'])
    train, val, params = data_processing(TRAIN_PATH, VAL_PATH, params)
    train_set, val_set =  make_dataset(train, val, params, shuffle=True, batch_size=params['batch_size'])
        
    # train logistic regression for baseline score
    print(f'Training linear model')
    clf = LogisticRegression(random_state=0, max_iter = 300)
    clf.fit(train.drop(params['TARGET'], axis=1), train[params['TARGET']])
    preds = clf.predict_proba(val.drop(params['TARGET'], axis=1))
    roc_auc = roc_auc_score(val[params['TARGET']], preds[:,1])
    add_metrics(key='Linear model', value=roc_auc, order=1)
    
    if params['net_type'] == 'linear': model = LinearM(params)
    if params['net_type'] == 'embeddings': model = TabNet(params)
    
    device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
    
    # TODO: move problem type to params
    
    looper = Looper(device, 'cls', add_metrics)
    
    model.cuda()
    torch.save(model.state_dict(),EXP_NAME+'.pth')
    optimizer = optim.AdamW(model.parameters(), lr=params['lr'], weight_decay=1e-06)
    loss_fn = torch.nn.CrossEntropyLoss()

    val_funcs = [roc_auc_score, accuracy_score]
    print(f'Training neural {params["net_type"]}')
    looper.train(model, 
            10,
            train_set, 
            val_set,
            optimizer,
            loss_fn,
            val_funcs)
    
    torch.save(model.state_dict(),EXP_NAME+'.pth')
    return float(max(looper.history()['roc_auc_score']))
Esempio n. 12
0
 def __init__(self):
     persistent_attrs_init(self)
     self.synth = Fluidsynth()
     self.devicechains = [DeviceChain(self, i) for i in range(16)]
     self.grids = []
     self.cpu = CPU(self)
     self.clock = Clock(self)
     self.looper = Looper(self)
     self.mixer = Mixer(self)
     # FIXME: probably make this configurable somehow (env var...?)
     if False:
         from termpad import ASCIIGrid
         self.grids.append(ASCIIGrid(self, 0, 1))
Esempio n. 13
0
def main():
    looper = Looper(16, 4)
    display = CursesDisplay(looper)
    arduino_input = ArduinoInput(lambda x: callback(x, looper, display))

    arduino_input.choose_port()
    arduino_input.start()
    looper.print_record_info()

    #
    try:
        display.run()
    except KeyboardInterrupt:
        pass

    arduino_input.stop()
    looper.stop()
Esempio n. 14
0
	def stop(self):
		Looper.stop(self)
		self.mout.close()
		pygame.midi.quit()
Esempio n. 15
0
from fizz_buzz_runner import FizzBuzzRunner
from printer import Printer
from inputer import Inputer
from looper import Looper

if __name__ == '__main__':
    inputer = Inputer()
    printer = Printer()
    runner = FizzBuzzRunner(inputer, printer)
    looper = Looper(runner, inputer)
    looper.loop()
Esempio n. 16
0
##
from looper import Looper
import threading
from interface import GetchInterface

cname = 'getch'

gi = GetchInterface(output_port_name=cname)
looper = Looper(controller_name=cname)

threading.Thread(target=looper.run).start()
gi.run()

##
Esempio n. 17
0
 def setUp(self):
     self.looper = Looper(wait=0)
Esempio n. 18
0
class LooperTest(unittest.TestCase):
    def setUp(self):
        self.looper = Looper(wait=0)

    def dummy(self):
        pass

    def dummy2(self):
        pass

    def stopper(self):
        self.looper.stop()

    def test_empty_loop_exits(self):
        self.looper.loop()

    def test_stop_stops(self):
        self.looper.enqueue_now(self.stopper)
        self.looper.enqueue_now(self.dummy)
        self.looper.enqueue_now(self.dummy)

        self.looper.loop()

        self.assertEquals(2, self.looper.size())

    def test_enqueue_now(self):
        # race condition - will fail sometimes
        time = Time.now()
        self.looper.enqueue_now(self.dummy)
        self.assertEquals(1, self.looper.size())
        self.assertEquals(time, self.looper._queue[0].time)

    def test_enqueue_next(self):
        self.looper.enqueue_now(self.dummy)
        self.looper.enqueue_next(self.dummy2)
        self.assertEquals(2, self.looper.size())
        self.assertEquals(0, self.looper._queue[0].time)
        self.assertEquals(self.dummy2, self.looper._queue[0].func)

    def test_enqueue_with_millis(self):
        # race condition - will fail sometimes
        time = Time.millis_from_now(1000)
        self.looper.enqueue(1000, self.dummy)
        self.assertEquals(1, self.looper.size())
        self.assertEquals(time, self.looper._queue[0].time)

    def test_enqueue_with_datetime(self):
        d = datetime(2016, 1, 1, 12, 12, 12)
        self.looper.enqueue(d, self.dummy)
        self.assertEquals(1, self.looper.size())
        self.assertEquals(Time.on_date(d), self.looper._queue[0].time)

    def test_enqueue_with_date(self):
        d = date(2016, 1, 1)
        self.looper.enqueue(d, self.dummy)
        self.assertEquals(1, self.looper.size())
        self.assertEquals(Time.on_date(d), self.looper._queue[0].time)

    def test_enqueue_with_timedelta(self):
        # race condition - will fail sometimes
        d = timedelta(milliseconds=340)
        self.looper.enqueue(d, self.dummy)
        self.assertEquals(1, self.looper.size())
        self.assertEquals(Time.after_timedelta(d), self.looper._queue[0].time)

    def test_enqueue_at(self):
        # race condition - will fail sometimes
        time = Time.millis_from_now(1000)
        self.looper.enqueue_at(time, self.dummy)
        self.assertEquals(1, self.looper.size())
        self.assertEquals(time, self.looper._queue[0].time)

    def test_size(self):
        self.assertEquals(0, self.looper.size())

        self.looper.enqueue_now(self.stopper)
        self.assertEquals(1, self.looper.size())

        self.looper.enqueue_now(self.stopper)
        self.assertEquals(2, self.looper.size())

        self.looper.loop()

        self.assertEquals(1, self.looper.size())
Esempio n. 19
0
def train(dataset_name: str, network_architecture: str, learning_rate: float,
          weight_decay: float, epochs: int, batch_size: int,
          horizontal_flip: float, vertical_flip: float, unet_filters: int,
          convolutions: int, dropout_prob: float, plot: bool):
    """Train chosen model on selected dataset."""
    # use GPU if avilable
    device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
    print(device)
    dataset = {}  # training and validation HDF5-based datasets
    dataloader = {}  # training and validation dataloaders

    for mode in ['train', 'valid']:
        # expected HDF5 files in dataset_name/(train | valid).h5
        data_path = os.path.join(dataset_name, f"{mode}.h5")
        # turn on flips only for training dataset
        dataset[mode] = H5Dataset(data_path,
                                  horizontal_flip if mode == 'train' else 0,
                                  vertical_flip if mode == 'train' else 0)
        dataloader[mode] = torch.utils.data.DataLoader(dataset[mode],
                                                       batch_size=batch_size)

    # only UCSD dataset provides greyscale images instead of RGB
    input_channels = 1 if dataset_name == 'ucsd' else 3

    # initialize a model based on chosen network_architecture
    network = {
        'UNet': UNet,
        'UNet2': UNet2,
        'UNet2_MC': UNet2_MC,
        'UNet_MC': UNet_MC,
        'FCRN_A': FCRN_A,
        'FCRN_A_MC': FCRN_A_MC
    }[network_architecture](input_filters=input_channels,
                            filters=unet_filters,
                            N=convolutions,
                            p=dropout_prob).to(device)
    network = torch.nn.DataParallel(network)

    # initialize loss, optimized and learning rate scheduler
    loss = torch.nn.MSELoss()
    #loss = torch.nn.L1Loss()
    optimizer = torch.optim.SGD(network.parameters(),
                                lr=learning_rate,
                                momentum=0.9,
                                weight_decay=weight_decay)  #1e-5
    lr_scheduler = torch.optim.lr_scheduler.StepLR(optimizer,
                                                   step_size=20,
                                                   gamma=0.1)
    # prob
    epochs__ = 'epochs=' + str(epochs)
    batch_size__ = 'batch=' + str(batch_size)
    horizontal_flip__ = 'hf=' + str(horizontal_flip)
    vertical_flip__ = 'vf=' + str(vertical_flip)
    unet_filters__ = 'uf=' + str(unet_filters)
    convolutions__ = "conv" + str(convolutions)
    prob_label = 'p=' + str(dropout_prob)
    weightdecay__ = "wd=" + str(weight_decay)

    # if plot flag is on, create a live plot (to be updated by Looper)
    if plot:
        pyplot.ion()
        fig, plots = pyplot.subplots(nrows=2, ncols=2)
    else:
        plots = [None] * 2

    # create training and validation Loopers to handle a single epoch
    train_looper = Looper(network, device,
                          loss, optimizer, dataloader['train'],
                          len(dataset['train']), plots[0], False)

    valid_looper = Looper(network,
                          device,
                          loss,
                          optimizer,
                          dataloader['valid'],
                          len(dataset['valid']),
                          plots[1],
                          False,
                          validation=True)

    train_looper.LOG = True
    valid_looper.LOG = False

    # current best results (lowest mean absolute error on validation set)
    current_best = np.infty

    for epoch in range(epochs):
        print(f"Epoch {epoch + 1}\n")

        # run training epoch and update learning rate
        train_looper.run()
        lr_scheduler.step()

        # run validation epoch
        with torch.no_grad():
            result = valid_looper.run()

        # update checkpoint if new best is reached
        if result < current_best:
            current_best = result
            torch.save(
                network.state_dict(),
                f'{dataset_name}_{network_architecture}_{epochs__}_{batch_size__}_{horizontal_flip__}_{vertical_flip__}_{unet_filters__}_{convolutions__}_{prob_label}_{weightdecay__}.pth'
            )
            hist = []
            hist.append(valid_looper.history[-1])
            hist.append(train_looper.history[-1])
            #hist = np.array(hist)
            #print(hist)
            np.savetxt(
                f'hist_best_{dataset_name}_{network_architecture}_{epochs__}_{batch_size__}_{horizontal_flip__}_{vertical_flip__}_{unet_filters__}_{convolutions__}_{prob_label}_{weightdecay__}.csv',
                hist,
                delimiter=',')

            print(f"\nNew best result: {result}")

        print("\n", "-" * 80, "\n", sep='')

        if plot:
            fig.savefig(
                f'status_{dataset_name}_{network_architecture}_{epochs__}_{batch_size__}_{horizontal_flip__}_{vertical_flip__}_{unet_filters__}_{convolutions__}_{prob_label}_{weightdecay__}.png'
            )

    print(f"[Training done] Best result: {current_best}")

    hist = np.array(train_looper.history)
    np.savetxt(
        f'hist_train_{dataset_name}_{network_architecture}_{epochs__}_{batch_size__}_{horizontal_flip__}_{vertical_flip__}_{unet_filters__}_{convolutions__}_{prob_label}_{weightdecay__}.csv',
        hist,
        delimiter=',')
    hist = np.array(valid_looper.history)
    np.savetxt(
        f'hist_test_{dataset_name}_{network_architecture}_{epochs__}_{batch_size__}_{horizontal_flip__}_{vertical_flip__}_{unet_filters__}_{convolutions__}_{prob_label}_{weightdecay__}.csv',
        hist,
        delimiter=',')

    train_looper.plots = None
    train_looper.validation = True
    train_looper.LOG = False
    train_looper.MC = True

    valid_looper.plots = None
    valid_looper.validation = True
    valid_looper.LOG = False
    valid_looper.MC = True

    NETname = network_architecture + '_' + prob_label + '_' + weightdecay__
    DATAname = dataset_name + '_train_'
    train_looper.MCdropOut(100, NETname, DATAname)
    DATAname = dataset_name + '_test_'
    valid_looper.MCdropOut(100, NETname, DATAname)
Esempio n. 20
0
def train(dataset_name: str,
          network_architecture: str,
          learning_rate: float,
          epochs: int,
          batch_size: int,
          horizontal_flip: float,
          vertical_flip: float,
          unet_filters: int,
          convolutions: int,
          plot: bool):
    """Train chosen model on selected dataset."""
    # use GPU if avilable
    device = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu')

    dataset = {}     # training and validation HDF5-based datasets
    dataloader = {}  # training and validation dataloaders

    for mode in ['train', 'valid']:
        # expected HDF5 files in dataset_name/(train | valid).h5
        data_path = os.path.join(dataset_name, f"{mode}.h5")
        # turn on flips only for training dataset
        dataset[mode] = H5Dataset(data_path,
                                  horizontal_flip if mode == 'train' else 0,
                                  vertical_flip if mode == 'train' else 0)
        dataloader[mode] = torch.utils.data.DataLoader(dataset[mode],
                                                       batch_size=batch_size)

    # only UCSD dataset provides greyscale images instead of RGB
    input_channels = 1 if dataset_name == 'ucsd' else 3

    # initialize a model based on chosen network_architecture
    network = {
        'UNet': UNet,
        'FCRN_A': FCRN_A
    }[network_architecture](input_filters=input_channels,
                            filters=unet_filters,
                            N=convolutions).to(device)
    network = torch.nn.DataParallel(network)

    # initialize loss, optimized and learning rate scheduler
    loss = torch.nn.MSELoss()
    optimizer = torch.optim.SGD(network.parameters(),
                                lr=learning_rate,
                                momentum=0.9,
                                weight_decay=1e-5)
    lr_scheduler = torch.optim.lr_scheduler.StepLR(optimizer,
                                                   step_size=20,
                                                   gamma=0.1)

    # if plot flag is on, create a live plot (to be updated by Looper)
    if plot:
        pyplot.ion()
        fig, plots = pyplot.subplots(nrows=2, ncols=2)
    else:
        plots = [None] * 2

    # create training and validation Loopers to handle a single epoch
    train_looper = Looper(network, device, loss, optimizer,
                          dataloader['train'], len(dataset['train']), plots[0])
    valid_looper = Looper(network, device, loss, optimizer,
                          dataloader['valid'], len(dataset['valid']), plots[1],
                          validation=True)

    # current best results (lowest mean absolute error on validation set)
    current_best = np.infty

    for epoch in range(epochs):
        print(f"Epoch {epoch + 1}\n")

        # run training epoch and update learning rate
        train_looper.run()
        lr_scheduler.step()

        # run validation epoch
        with torch.no_grad():
            result = valid_looper.run()

        # update checkpoint if new best is reached
        if result < current_best:
            current_best = result
            torch.save(network.state_dict(),
                       f'{dataset_name}_{network_architecture}.pth')

            print(f"\nNew best result: {result}")

        print("\n", "-"*80, "\n", sep='')

    print(f"[Training done] Best result: {current_best}")
Esempio n. 21
0
SYSTEM_MASS = 1.5
SYSTEM_POSITION = vector(0, 0, 0)
SYSTEM_INITIAL_VELOCITY = vector(5, 0, 0)
SYSTEM_INITIAL_POSITION = vector(0, 0, 0)
DELTA_T = 0.003

# Setup Display window for visualization
scene = display(width=640, height=480, background=color.white, range=2.5, title="VPython Test")
# Create object for visualization
ball = sphere(color=color.blue, radius=0.10)
# Create a track behind object to visualize trajectory
trail = curve(color=color.green, radius=0.02)
# Create small sphere to mark the origin in Display window
origin = sphere(pos=SYSTEM_POSITION, color=color.yellow, radius=0.04)

ball.m = SYSTEM_MASS

# noinspection PyPropertyAccess
ball.pos = SYSTEM_INITIAL_POSITION
ball.vel = SYSTEM_INITIAL_VELOCITY

looper = Looper(delta_t=DELTA_T)
looper.open_file()
looper.loop(ball, vector(0, 0, 0), .867)
looper.loop(ball, vector(-18.1,0,0), .074)
looper.loop(ball, vector(0,0,0), .634)
looper.close_file()



def train_boots(dataset_name: str, network_architecture: str,
                learning_rate: float, epochs: int, batch_size: int,
                horizontal_flip: float, vertical_flip: float,
                unet_filters: int, convolutions: int, plot: bool):
    """Train chosen model on selected dataset."""
    # use GPU if avilable
    device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
    print(device)
    dataset = {}  # training and validation HDF5-based datasets
    dataloader = {}  # training and validation dataloaders

    # only UCSD dataset provides greyscale images instead of RGB
    input_channels = 1 if dataset_name == 'ucsd' else 3

    # prob
    epochs__ = 'epochs=' + str(epochs)
    batch_size__ = 'batch=' + str(batch_size)
    horizontal_flip__ = 'hf=' + str(horizontal_flip)
    vertical_flip__ = 'vf=' + str(vertical_flip)
    unet_filters__ = 'uf=' + str(unet_filters)
    convolutions__ = "conv" + str(convolutions)

    dirr = 'boots_results_' + dataset_name

    Path(dirr).mkdir(parents=True, exist_ok=True)

    # if plot flag is on, create a live plot (to be updated by Looper)
    if plot:
        pyplot.ion()
        fig, plots = pyplot.subplots(nrows=2, ncols=2)
    else:
        plots = [None] * 2

    for mode in ['train', 'valid']:
        # expected HDF5 files in dataset_name/(train | valid).h5
        data_path = os.path.join(dataset_name, f"{mode}.h5")
        # turn on flips only for training dataset
        dataset[mode] = H5Dataset(data_path,
                                  horizontal_flip if mode == 'train' else 0,
                                  vertical_flip if mode == 'train' else 0)

    #train_indices = torch.zeros_like(dataset[mode].shape[0])

    n_samples = len(dataset['train'])

    #print("******", n_samples)
    sampling_ratio = int(0.63 * n_samples)
    results_train = []
    results_test = []

    for i in range(20):
        # initialize a model based on chosen network_architecture
        network = {
            'UNet': UNet,
            'UNet2': UNet2,
            'FCRN_A': FCRN_A,
        }[network_architecture](input_filters=input_channels,
                                filters=unet_filters,
                                N=convolutions,
                                p=0).to(device)
        network = torch.nn.DataParallel(network)

        # initialize loss, optimized and learning rate scheduler
        loss = torch.nn.MSELoss()
        optimizer = torch.optim.SGD(network.parameters(),
                                    lr=learning_rate,
                                    momentum=0.9,
                                    weight_decay=1e-5)
        lr_scheduler = torch.optim.lr_scheduler.StepLR(optimizer,
                                                       step_size=20,
                                                       gamma=0.1)

        ntrain = torch.randperm(n_samples)[:sampling_ratio]

        sampler = torch.utils.data.SubsetRandomSampler(ntrain)

        dataloader['train'] = torch.utils.data.DataLoader(
            dataset['train'], batch_size=batch_size, sampler=sampler)

        dataloadertrain2 = torch.utils.data.DataLoader(dataset['train'],
                                                       batch_size=batch_size)

        dataloader['valid'] = torch.utils.data.DataLoader(dataset['valid'],
                                                          batch_size=1)

        # create training and validation Loopers to handle a single epoch
        train_looper = Looper(network, device, loss,
                              optimizer, dataloader['train'],
                              len(dataset['train']), plots[0], False)

        train_looper.LOG = True

        # current best results (lowest mean absolute error on validation set)
        current_best = np.infty

        for epoch in range(epochs):
            print(f"Epoch {epoch + 1}\n")

            # run training epoch and update learning rate
            result = train_looper.run()
            lr_scheduler.step()

            # update checkpoint if new best is reached
            if result < current_best:
                current_best = result
                torch.save(
                    network.state_dict(),
                    os.path.join(
                        dirr,
                        f'{dataset_name}_boot_i={i}_{network_architecture}_{epochs__}_{batch_size__}_{horizontal_flip__}_{vertical_flip__}_{unet_filters__}_{convolutions__}.pth'
                    ))
                hist = []
                #hist.append(valid_looper.history[-1])
                hist.append(train_looper.history[-1])
                #hist = np.array(hist)
                #print(hist)
                np.savetxt(os.path.join(
                    dirr,
                    f'hist_best_boot_{dataset_name}_{network_architecture}_i={i}_{epochs__}_{batch_size__}_{horizontal_flip__}_{vertical_flip__}_{unet_filters__}_{convolutions__}.csv'
                ),
                           hist,
                           delimiter=',')

                print(f"\nNew best result: {result}")

            print("\n", "-" * 80, "\n", sep='')

            if plot:
                fig.savefig(
                    os.path.join(
                        dirr,
                        f'status_boot_i={i}_{dataset_name}_{network_architecture}_{epochs__}_{batch_size__}_{horizontal_flip__}_{vertical_flip__}_{unet_filters__}_{convolutions__}.png'
                    ))

        network.load_state_dict(
            torch.load(
                os.path.join(
                    dirr,
                    f'{dataset_name}_boot_i={i}_{network_architecture}_{epochs__}_{batch_size__}_{horizontal_flip__}_{vertical_flip__}_{unet_filters__}_{convolutions__}.pth'
                )))

        valid_looper = Looper(network,
                              device,
                              loss,
                              optimizer,
                              dataloader['valid'],
                              len(dataset['valid']),
                              None,
                              False,
                              validation=True)

        train_looper2 = Looper(network,
                               device,
                               loss,
                               optimizer,
                               dataloadertrain2,
                               len(dataloadertrain2),
                               None,
                               False,
                               validation=True)

        valid_looper.LOG = False
        train_looper2.LOG = False
        valid_looper.MC = False

        with torch.no_grad():
            valid_looper.run()
            train_looper2.run()

        if i == 0:
            results_train.append(train_looper2.true_values)
            results_test.append(valid_looper.true_values)

        results_train.append(train_looper2.predicted_values)
        results_test.append(valid_looper.predicted_values)

        print(f"[Training done] Best result: {current_best}")

        hist = np.array(train_looper.history)
        np.savetxt(os.path.join(
            dirr,
            f'hist_train_boot_i={i}_{dataset_name}_{network_architecture}_{epochs__}_{batch_size__}_{horizontal_flip__}_{vertical_flip__}_{unet_filters__}_{convolutions__}.csv'
        ),
                   hist,
                   delimiter=',')
        hist = np.array(valid_looper.history)
        np.savetxt(os.path.join(
            dirr,
            f'hist_test_boot_i={i}_{dataset_name}_{network_architecture}_{epochs__}_{batch_size__}_{horizontal_flip__}_{vertical_flip__}_{unet_filters__}_{convolutions__}.csv'
        ),
                   hist,
                   delimiter=',')

    results_train = np.array(results_train)
    results_train = results_train.transpose()
    np.savetxt(os.path.join(
        dirr,
        f'predicted_train_best_boot_{dataset_name}_{network_architecture}_{epochs__}_{batch_size__}_{horizontal_flip__}_{vertical_flip__}_{unet_filters__}_{convolutions__}.csv'
    ),
               results_train,
               delimiter=',')

    results_test = np.array(results_test)
    results_test = results_test.transpose()
    np.savetxt(os.path.join(
        dirr,
        f'predicted_test_best_boot_{dataset_name}_{network_architecture}_{epochs__}_{batch_size__}_{horizontal_flip__}_{vertical_flip__}_{unet_filters__}_{convolutions__}.csv'
    ),
               results_test,
               delimiter=',')
Esempio n. 23
0
class App:
    def __init__(self):
        self.ipc = IpcServer(
        )  # Start IPC to webserver (server-side): mandatory but there might not be a client connecting to it
        self.osc = OscServer(
        )  # Start app OSC server: mandatory but there might not be a client connecting to it
        self.looper = Looper(
        )  # Start sooperlooper: optional (disable with --no-looper)
        self.recorder = Recorder(
        )  # Init audio recorder: always on but no background activity
        self.drum_sequencer = DrumSequencer(
        )  # Init audio/drums player: always on but no background activity

        # Only start MIDI receiver thread if USBMIDI device (foot pedal) is connected
        self.midi_receiver = MidiReceiver(
            'USBMIDI', self) if utility.check_midi(['USBMIDI']) else None

        self._handlers = {}

    def quit(self):
        logging.info('Exiting')

        if self.looper and self.looper.is_running:
            self.looper.stop()

        self.ipc.stop()

        sys.exit(0)

    def send_event(self, event_target, event_payload):
        logging.debug('Event: {} {}'.format(event_target, event_payload))
        if event_target == MidiMapping.EVENT_TARGET_PRESET:
            self._handlers['presets'].trigger_preset(event_payload)
        elif event_target == MidiMapping.EVENT_TARGET_MIDI_LOOP:
            self._handlers['midi'].toggle(event_payload)
        elif event_target == MidiMapping.EVENT_TARGET_LOOPER:
            self._handlers['looper'].send_osc(event_payload)
        elif event_target == MidiMapping.EVENT_TARGET_DRUMS:
            self._handlers['drums'].play_song()

    def _parse_arguments(self):
        parser = argparse.ArgumentParser()
        parser.add_argument('-v',
                            help='verbose',
                            action='store_true',
                            default=False)
        parser.add_argument('--no-looper',
                            help='don\'t start looper',
                            action='store_true',
                            default=False)
        return parser.parse_args()

    def main(self):
        # Parse program arguments
        self.args = self._parse_arguments()
        logging.debug(self.args)

        # System checks
        assert utility.check_sound_card('card 0:'), 'No ALSA device found'
        # assert check_sound_card('card 1:'), 'USB DAC not found'
        # assert utility.check_processes(['jackd']), 'jackd must be running'
        assert utility.check_midi(['System',
                                   'Midi Through']), 'No MIDI devices found'
        # assert check_midi(['USBMIDI']), 'USB foot controller not found'

        Menu.ui = TkUi(fullscreen=True, fontsize=56)

        self.ipc.start()

        if not self.args.no_looper:
            self.looper.start()

        main_menu = Menu('main')
        submenus = {
            name: Menu(name, main_menu)
            for name in [
                'midi', 'presets', 'looper', 'record', 'drums', 'utilities',
                'system'
            ]
        }

        # Create main menu
        BaseMenuHandler.app = self
        self._handlers['midi'] = MidiExpanderHandler(submenus['midi'])
        self._handlers['presets'] = PresetsHandler(submenus['presets'])
        self._handlers['looper'] = LooperHandler(submenus['looper'])
        self._handlers['record'] = RecordHandler(submenus['record'])
        self._handlers['drums'] = DrumsHandler(submenus['drums'],
                                               self.drum_sequencer)
        self._handlers['utilities'] = UtilitiesHandler(submenus['utilities'])
        self._handlers['system'] = SystemHandler(submenus['system'])

        self._handlers['record'].recorder = self.recorder

        main_menu.make_ui()
        Menu.ui.mainloop()
Esempio n. 24
0
class RedditReader:
    def __init__(self):
        self.looper = Looper(wait=0.01)
        self.client = HttpsSocketAsync(self.looper, 'www.reddit.com')

    def request_top_post(self, subreddit, n=4):
        url = '/r/{0}/top.json?sort=top&t=day&limit={1}'.format(subreddit, n)
        self.client.request("GET", url, ExtensibleCallback(self.on_response))

    def on_response(self, response):
        if response.status == 200:
            json_body = json.loads(response.read())
            self.on_json(json_body)
        else:
            self.on_http_error(None, response)

    def on_json(self, response):
        for post in response['data']['children']:
            data = post["data"]
            print u"/r/{subreddit:<12} {ups:>4}↕{downs:<3} {title} ({url})".format(
                **data)

    def run(self):
        self.looper.enqueue_now(self.request_top_post, "python")
        self.looper.enqueue_now(self.request_top_post, "programming")
        self.looper.enqueue_now(self.request_top_post, "java")
        self.looper.enqueue_now(self.request_top_post, "android")
        self.looper.enqueue_now(self.request_top_post, "vive")
        self.looper.loop()

    def on_http_error(self, url, response):
        print "Error {0} at {1}".format(response.status, url)
        for header in response.getheaders():
            print header
        self.looper.stop()
Esempio n. 25
0
 def __init__(self):
     self.looper = Looper(wait=0.01)
     self.client = HttpsSocketAsync(self.looper, 'www.reddit.com')
Esempio n. 26
0
from flask import Flask, jsonify
from time import sleep
import requests
import threading
import os
from looper import Looper

app = Flask(__name__)

# instantiate looper object and start background processing
# add this crazy hack, otherwise it will be called twice:
if (app.debug
        and os.environ.get('WERKZEUG_RUN_MAIN') == 'true') or not app.debug:
    lp = Looper()
    thread = threading.Thread(target=lp.start)
    thread.start()


@app.route('/api/motion-state', methods=['GET'])
def getCurState():
    return jsonify({"msg": "Current state: {}".format(lp.curState())})


@app.route('/api/motion-state/<int:state>', methods=['PATCH'])
def toggleMotionDetect(state):

    # stop background process
    if state == 0:
        lp.stop()
        return jsonify({"msg": "Process stopped"})
Esempio n. 27
0
        if (hit == 1 and hit_elapse > 0.1):
            #print(last)
            play_region(instr,last) 
            hit_wait = time.time() 



    
# def record(instr):

#BOOT UP STUFF, THIS SHOULD BE IN ITS OWN FILE 
#set sequences

TEMPO = 5    #how many instruments
CHANNELS = 5
looper = Looper(TEMPO, CHANNELS)#5 is the tempo, 2 channels, 8 steps
mixer = mix()
mixer.update_channel_volume(0, 1.0)


# kick =       [1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0]
# open_hat =   [1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0]
# snare =      [0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0]
# closed_hat = [0,1,0,1,0,1,0,0,0,1,0,1,0,1,0,0]
# empty_arr =  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]

kick =       [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
open_hat =   [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
snare =      [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
closed_hat = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
empty_arr =  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
Esempio n. 28
0
                 play_region(instr, 1)
            if (open_hat[last] == 1):
                play_region(instr, 0)
            


        


        


#settig up channel data
TEMPO = 5    #how many instruments
CHANNELS = 4
looper = Looper(TEMPO, CHANNELS)#5 is the tempo, 2 channels, 8 steps
mixer = mix()
mixer.update_channel_volume(0, 1.0)
#start loop on sequencer

start_loop(looper)

       

            
    
        
        
        
    
Esempio n. 29
0
class MusicBox:
    OSC_MODES = {
        'preset': Mode.PRESET,
        'stomp': Mode.STOMP,
        'looper': Mode.LOOPER,
        'metronome': Mode.METRONOME
    }

    def __init__(self):
        self._log = logging.getLogger('musicbox.MusicBox')

        # Internal attributes
        self._selected_stompbox = 1  # 0 = global parameters, 1-8 = actual stompboxes
        self._current_mode = Mode.PRESET
        self._last_slider_update_time = 0

        # OSC inputs (footpedal)
        try:
            self._midi_to_osc = MidiToOsc(
                'Arduino Micro')  # works via callbacks, so not blocking
        except ValueError as e:
            self._log.error('Failed to start Midi Footpedal: ' + str(e))

        # OSC server (receives inputs)
        self._osc_server = FootpedalOscServer(self.cb_mode, self.cb_preset,
                                              self.cb_stomp, self.cb_looper,
                                              self.cb_metronome,
                                              self.cb_slider)

        # mod-host LV2 host (output)
        self._banks_manager = BanksManager()
        self._banks_manager.append(
            Bank('Bank 1'))  # TODO: load banks from stored files
        self._modhost = ModHost('localhost')
        self._modhost.connect()
        self._banks_manager.register(self._modhost)
        self._pedalboard = None
        self._log.info("STARTED mod-host client")

        # Metronome output (using klick)
        self._metronome = Metronome()
        self._log.info("STARTED Metronome")

        # Looper object (using sooperlooper)
        self._looper = Looper()
        self._log.info("STARTED Looper")

        # Notifiers
        self._notifier = TcpNotifier()
        self._log.info("STARTED TcpNotifier")

        # Initialize: set mode PRESET and load preset1
        time.sleep(2)
        self._set_mode(Mode.PRESET)
        for preset_id in range(4):
            self._load_preset('preset{:02d}.yaml'.format(preset_id))

    def run(self):
        try:
            self._osc_server.start()
            self._osc_server._thread.join()
        except KeyboardInterrupt:
            self._log.warn('KeyboardInterrupt: shutting down')
            self._osc_server.stop()
            self._notifier.close()

    def _set_mode(self, mode):
        midisend(1, mode.value)

        # Action when leaving mode
        if mode != Mode.LOOPER:
            self._looper.enable(False)
        if mode != Mode.METRONOME:
            self._metronome.enable(False)

        # Action based on activated mode
        if mode == Mode.PRESET:
            pass
        elif mode == Mode.STOMP:
            self._activate_preset(0)  # special preset 0 = stompbox mode
        elif mode == Mode.LOOPER:
            self._looper.enable(True)
        elif mode == Mode.METRONOME:
            self._metronome.enable(True)

        self._current_mode = mode

        self._notifier.update("MODE:{:d}".format(int(
            self._current_mode.value)))

    def _create_graph_from_config(self, filename):
        """
        Loads a YAML file (could easily support JSON as well) and creates
        a graph for defined plugins and connections. Also returns
        other settings separately.
        """
        with open(filename, 'r') as f:
            data = yaml.safe_load(f)

        settings = {
            'name': data['preset']['name'],
            'author': data['preset']['author'],
            'global_parameters': data['preset']['global_parameters']
        }

        self._log.debug('yaml preset data: ' + str(data['preset']))

        plugins = [
            Lv2Plugin(sb['lv2'], sb['connections'])
            for sb in data['preset']['stompboxes']
        ]
        pb = PedalboardGraph(plugins)

        # Disable stompboxes if configured
        for i, sb in enumerate(data['preset']['stompboxes']):
            if 'enabled' in sb:
                plugins[i].is_enabled = sb['enabled']

        # Assign index to each node
        for p in pb.nodes:
            p._index = pb.get_index(p)

        # Add graph edges (connections between effects as index to node - mod_host module will do conversion to "effect_:in" string)
        for p in pb.nodes:
            self._log.debug('Adding edges {!s} for node {!s}'.format(
                p._connections, p))
            pb.add_edges(p, p._connections)

        self._log.debug("Graph with edges:\n" + str(pb))
        pb.settings = settings
        return pb

    def _activate_preset(self, preset_id):
        # Store current pedalboard in attribute
        self._pedalboard = self._banks_manager.banks[0].pedalboards[preset_id]

        # Load new pedalboard into mod-host
        self._modhost.pedalboard = self._pedalboard
        self._log.info('Activated pedalboard {!s}'.format(self._pedalboard))

        # Notifications
        self._preset_info_notifier_update(preset_id)

        for e in self._pedalboard.effects:
            e.toggle()
            self._notifier.update("STOMPEN:{:d}:{:d}".format(
                e.index, int(e.active)))

    def _load_preset(self, yaml_file, remove_previous=False):
        # Create graph with effect plugin objects
        graph = self._create_graph_from_config(yaml_file)

        # Cleanup existing pedalboard in mod-host
        if remove_previous and self._pedalboard is not None:
            for e in list(self._pedalboard.effects):
                for c in list(e.connections):
                    self._pedalboard.disconnect(c.output, c.input)
                self._pedalboard.effects.remove(e)
            self._banks_manager.banks[0] = []
            del self._pedalboard

        # Create PedalPi pedalboard and add to bank and mod-host
        pedalboard = Pedalboard(graph.settings['name'])
        pedalboard.graph = graph
        self._banks_manager.banks[0].append(pedalboard)

        # Add nodes (effects) to mod-host
        lv2_builder = Lv2EffectBuilder()
        for node in graph.nodes:  # loop over Plugin objects
            self._log.info("mod-host: add effect " + str(node))
            node.effect = lv2_builder.build(node.uri)
            pedalboard.effects.append(node.effect)

        sys_effect = SystemEffect('system', ['capture_1', 'capture_2'],
                                  ['playback_1', 'playback_2'])

        # Connect system capture to first effect
        pedalboard.connect(sys_effect.outputs[0],
                           pedalboard.effects[0].inputs[0])

        # Add edges (connections) to mod-host
        for node in graph.nodes:  # looper over Plugin objects
            incoming = graph.get_incoming_edges(node)
            outgoing = graph.get_outgoing_edges(node)
            self._log.info(
                'mod-host: add connection {!s} -> [{:d}] "{:s}" -> {!s}'.
                format(incoming, node.index, node.name, outgoing))

            # Go through outgoing edges (indices)
            for e in outgoing:  # loop over edge indices
                # Connect current effect to effect given by index e
                neighbor = graph.get_node_from_index(e)
                if node.has_stereo_output and neighbor.has_stereo_input:  # stereo to stereo
                    pedalboard.connect(node.effect.outputs[0],
                                       neighbor.effect.inputs[0])
                    pedalboard.connect(node.effect.outputs[1],
                                       neighbor.effect.inputs[1])
                elif not node.has_stereo_output and neighbor.has_stereo_input:  # split mono to stereo
                    pedalboard.connect(node.effect.outputs[0],
                                       neighbor.effect.inputs[0])
                    pedalboard.connect(node.effect.outputs[0],
                                       neighbor.effect.inputs[1])
                elif node.has_stereo_output and not neighbor.has_stereo_input:  # sum stereo to mono
                    pedalboard.connect(node.effect.outputs[0],
                                       neighbor.effect.inputs[0])
                    pedalboard.connect(node.effect.outputs[1],
                                       neighbor.effect.inputs[0])
                else:  # mono to mono
                    pedalboard.connect(node.effect.outputs[0],
                                       neighbor.effect.inputs[0])

            if outgoing == []:
                left_output = node.effect.outputs[0]
                right_output = node.effect.outputs[1 if node.
                                                   has_stereo_output else 0]
                pedalboard.connect(left_output, sys_effect.inputs[0])
                pedalboard.connect(right_output, sys_effect.inputs[1])

    def _handle_slider_stompbox(self, slider_id, value):
        stompbox = self._pedalboard.graph.nodes[
            self._selected_stompbox -
            1]  # select by index from list of Plugin objects
        param_name, param_info = stompbox.get_parameter_info_by_index(
            slider_id - 1)
        if param_name is None:
            self._log.info('{!s} has no parameter for slider {:d}'.format(
                stompbox, slider_id))
            return

        self._log.debug('{:s} param_info {!s}'.format(param_name, param_info))

        # Convert slider value (0-1023) to parameters (min, max) range
        min_max_ratio = 1024 / (param_info['Maximum'] - param_info['Minimum'])
        value /= min_max_ratio
        value += param_info['Minimum']

        self._log.info(
            'Setting stomp #{:d} param #{:d} "{:s}" [{:s}] to {} (ratio {})'.
            format(self._selected_stompbox, slider_id, param_name,
                   param_info['Symbol'], value, min_max_ratio))
        stompbox.effect.params[slider_id - 1].value = value
        self._notifier.update("SLIDER:{:d}:{:f}".format(slider_id - 1, value))

    def cb_mode(self, uri, msg=None):
        """Handle incoming /mode/... OSC message"""
        mode = uri.rsplit('/', 1)[-1]
        assert mode in self.OSC_MODES.keys()
        self._log.info("MODE {} -> {}".format(mode, self.OSC_MODES[mode]))
        self._set_mode(self.OSC_MODES[mode])

    def _preset_info_notifier_update(self, preset_id):
        # Construct JSON payload for notifiers:
        # current preset, list of stompboxes with parameters
        notifier_data = {
            'preset_id': int(preset_id),
            'preset_name': self._pedalboard.graph.settings['name'],
            'stompboxes': []
        }

        # Loop over all stompboxes (nodes on pedalboard graph)
        for sb in self._pedalboard.graph.nodes:
            sb_data = {'name': sb.name, 'parameters': []}

            # Loop over stombox's parameters
            assert len(sb.parameters) == len(sb.effect.parameters)
            for i, p in enumerate(
                    sb.parameters):  # p is { 'NAME': { params } }
                assert len(p.keys()) == 1
                p_name = list(p.keys())[0]
                param_data = {
                    'name': p_name,
                    'symbol': p[p_name]['Symbol'],
                    'min': p[p_name]['Minimum'],
                    'max': p[p_name]['Maximum'],
                    'value': sb.effect.parameters[i]
                }
                sb_data['parameters'].append(param_data)

            notifier_data['stompboxes'].append(sb_data)

        self._log.debug("Sending JSON: " + json.dumps(notifier_data))
        self._notifier.update("PRESET:" + json.dumps(notifier_data))

    def cb_preset(self, uri, msg=None):
        """Handle incoming /preset/<N> OSC message"""
        preset_id = int(uri.rsplit('/', 1)[-1])
        assert 0 < preset_id < 100
        self._log.info("PRESET {:d}".format(preset_id))
        self._activate_preset(preset_id)

    def cb_stomp_enable(self, uri, msg=None):
        """Handle incoming /stomp/<N>/enable OSC message"""
        uri_splits = uri.split('/')[2:]  # throw away leading "/" and "stomp"
        assert 2 <= len(uri_splits) <= 3, uri_splits
        stomp_id = int(uri_splits[0])
        op = uri_splits[1]
        value = int(uri_splits[2]) if len(uri_splits) == 3 else None

        self._log.debug('cb_stomp_{}: {:d} (value {!s})'.format(
            op, stomp_id, value))
        assert 0 < stomp_id < 10
        assert op in ['enable', 'select']

        if op == 'select':
            self._selected_stompbox = stomp_id
            self._notifier.update(
                "STOMPSEL:{:d}".format(self._selected_stompbox - 1))
        elif op == 'enable':
            assert self._pedalboard
            p = self._pedalboard.graph.get_node_from_index(stomp_id - 1)
            if p:
                assert p.index == stomp_id - 1
                if value is None:  # no value given: toggle internal state
                    p.is_enabled = not p.is_enabled
                else:
                    p.is_enabled = bool(value)

                self._log.info('STOMP {} "{}" ENABLE {:d}'.format(
                    p.index, p.name, p.is_enabled))
                p.effect.active = True if not p.is_enabled else False
                self._notifier.update("STOMPEN:{:d}:{:d}".format(
                    p.index, p.is_enabled))
            else:
                self._log.warn(
                    'cb_stomp_enable: node with index {:d} not in pedalboard'.
                    format(stomp_id - 1))

    def cb_looper(self, uri, msg=None):
        """Handle incoming /looper OSC messages to be proxied to sooperlooper"""
        _, command = uri.rsplit('/', 1)
        cmd_fn = {
            'undo': self._looper.undo,
            'redo': self._looper.redo,
            'record': lambda: self._looper.record(insert=False),
            'overdub': lambda: self._looper.overdub(multiply=False),
            'mute_trigger': lambda: self._looper.mute(trigger=True),
            'insert': lambda: self._looper.record(insert=True),
            'multiply': lambda: self._looper.overdub(multiply=True),
            'pause': self._looper.pause,
        }
        if command in cmd_fn:
            cmd_fn[command]()
            self._log.info(
                "Sent /sl/0/hit s:{:s} to sooperlooper".format(command))
        else:
            self._log.error(
                "Invalid sooperlooper command {:s}".format(command))

    def cb_metronome(self, uri, msg=None):
        """Handle incoming /metronome/ OSC messages"""
        uri_splits = uri.split('/')
        assert uri_splits[0] == ''
        assert uri_splits[1] == 'metronome'
        command = uri_splits[2]

        self._log.info("METRONOME {}".format(command))

        if command == 'pause':
            self._metronome.enable(not self._metronome.is_running)
        elif command == 'set_bpm':
            assert len(uri_splits) == 4
            self._metronome.set_bpm(int(uri_splits[3]))
        elif command == 'inc_bpm':
            self._metronome.set_bpm(self._metronome.bpm + 8)
        elif command == 'dec_bpm':
            self._metronome.set_bpm(self._metronome.bpm - 8)
        elif command == 'tap':
            self._metronome.tap()

        bpm = self._metronome.get_bpm()
        midisend(2, bpm)
        self._notifier.update("BPM:{:d}".format(bpm))

    def cb_slider(self, uri, msg=None):
        """Handle incoming /slider/<N> OSC message"""
        now = time.time()
        if now - self._last_slider_update_time < 0.2:
            return
        self._last_slider_update_time = now

        uri_splits = uri.split('/')
        assert uri_splits[0] == ''
        assert uri_splits[1] == 'slider'
        slider_id = int(uri_splits[2])
        value = float(msg) if msg is not None else float(uri_splits[3])
        self._log.info("SLIDER {:d} = {:f}".format(slider_id, value))

        if self._current_mode in [Mode.PRESET, Mode.STOMP]:
            # Adjust currently selected stompbox (default 1)
            self._handle_slider_stompbox(slider_id, value)
        elif self._current_mode == Mode.LOOPER:
            # Adjust looper parameters
            pass
        elif self._current_mode == Mode.METRONOME:
            if slider_id == 1:
                self._metronome.set_bpm(value)
            elif slider_id == 2:
                self._metronome.set_volume(value)