コード例 #1
0
ファイル: run.py プロジェクト: EQ4/versificator
    def gimme_loop_handler(cls, addr, tags, data, source):
        # time in seconds; key between 0 (for C) and 11 (for B)
        pd_looper_id, required_tempo, required_key = data[0], data[1], data[2]
        
        # If the track hasn't been registered yet, we do that
        pd_looper_infos = cls.pd_loopers.setdefault(pd_looper_id, {
            'current_loop_id': None,
            'track_ids': [],
            'tempo': None,
        })
        current_loop_id = pd_looper_infos['current_loop_id']

        # Picking the new loop in the pool
        with cls.pool_lock:

            # prefilter available loops (those whose track haven't been picked already)
            available_loops = cls.pool.values()
            forbidden_tracks = cls.forbidden_tracks(pd_looper_id)
            available_loops = filter(lambda l: l['track_id'] not in forbidden_tracks, available_loops)

            # Select the most suitable next loop according to the current loop.
            if current_loop_id is not None:
                def sort_key(l):
                    timbre_dist = loop_distance(cls.old_loops[current_loop_id], l)
                    tempo_dist = abs(1 - l['tempo'] / float(required_tempo)) * 40
                    return timbre_dist + tempo_dist
                loop_infos = sorted(available_loops, key=lambda l: sort_key)[0]
            else:
                loop_infos = available_loops[0]

            # Remove the loop from the pool, reserving the loop's track for this looper
            cls.pool.pop(loop_infos['loop_id'])
            pd_looper_infos['track_ids'].append(loop_infos['track_id'])
        pd_looper_infos['current_loop_id'] = loop_infos['loop_id']

        # Adding the picked looped to `old_loops`, so that we remember it
        # but it cannot be used again.
        with cls.old_loops_lock:
            cls.old_loops[loop_infos['loop_id']] = loop_infos
            if current_loop_id is not None: cls.old_loops.pop(current_loop_id)

        # Preparing the loop
        logger.info('sending new loop %s to looper %s, left : %s' % (loop_infos['path'], pd_looper_id, len(cls.pool)))
        loop = Sound.from_file(loop_infos['path'])
        required_length = loop.length * float(required_tempo) / loop_infos['tempo']
        beat_length = 60.0 / required_tempo
        required_length = round(required_length / beat_length) * beat_length
        loop = loop.time_stretch(required_length).fade(in_dur=0.002, out_dur=0.002)
        loop.to_file(loop_infos['path'])

        # Sending loop, and fill-up the pool if necessary.
        send_msg('/new_loop', pd_looper_id, loop_infos['path'], int(round(loop.length * 1000)), loop_infos['loop_id'])
        if len(LoopScraper.pool) < LoopScraper.pool_min_size: LoopScraper.wake_up_scrapers()
コード例 #2
0
ファイル: run.py プロジェクト: EQ4/versificator
    def scrape(self):
        id_counter = 0
        track_id, filename, sound_length = get_sound()

        # Check if the sound is long enough, and if yes we extract some loops from it.
        # TODO: make this less restrictive to waste a bit less
        if sound_length > 2 * self.sample_length:
            offset = 0
            upper_limit = sound_length - 2 * self.sample_length
            while (offset + 2 * self.sample_length < upper_limit):

                # Calculate a random offset where the loop will start
                offset = random.randint(offset, int(min(offset + sound_length * 0.2, upper_limit)))

                # Extracting a loop and saving it to 'loop<n>.wav'
                sample = Sound.from_file(filename, start=offset, end=offset+self.sample_length)
                loops = sample.extract_loops()
                for loop in loops:
                    if id_counter > 10:
                        offset = upper_limit
                        break
                    id_counter += 1
                    loop_id = '%s_%s' % (track_id, id_counter)
                    loop_path = self._get_free_path()
                    logger.info('loop extracted to %s' % loop_path)
                    loop.to_file(loop_path)
                    #key, key_confidence, length = loop.echonest.key, loop.echonest.key_confidence, loop.length

                    with self.pool_lock:
                        self.pool[loop_id] = dict(loop.loop_infos, **{
                            'path': loop_path,
                            'length': loop.length,
                            'loop_id': loop_id,
                            'track_id': track_id,
                            'timbre_start': loop.loop_infos['timbre_start'],
                            'timbre_end': loop.loop_infos['timbre_end']
                            #'key': (key, key_confidence)
                        })

                # Increment values for next loop
                offset += self.sample_length

                # Delete the sounds to save memory
                # We also have to collect manually because of a "bug" in pandas:
                # https://github.com/pydata/pandas/issues/2659
                if 'loop' in locals(): del loop
                del sample
                gc.collect()
コード例 #3
0
ファイル: run.py プロジェクト: EQ4/versificator
    def scrape(self):
        track_id, pad_path, pad_length = get_sound()
        new_pad_path = self._get_free_path()
        pad_id = '%s' % (track_id)
        sound = Sound.from_file(pad_path, end=min(30, pad_length))
        sound = sound.remove_beats()
        sound.to_file(new_pad_path)
        logger.info('pad extracted to %s' % new_pad_path)
        '''pad.to_file(pad_path)

        # Delete the sound to save memory
        # We also have to collect manually because of a "bug" in pandas:
        # https://github.com/pydata/pandas/issues/2659 
        del pad
        gc.collect()'''

        with self.pool_lock:
            self.pool[pad_id] = {
                'path': new_pad_path,
                'pad_id': pad_id
            }