コード例 #1
0
    def convert_sample_freq(self, sample_id, target_freq):
        # Get current data and format info
        cur_handle = self._get_sample_data_handle(sample_id, convert_to_float=True)
        channels = cur_handle.get_channels()
        cur_freq = cur_handle.get_audio_rate()
        cur_bits, cur_is_float = self.get_sample_format(sample_id) # original format

        ratio = target_freq / cur_freq

        # Get converted audio data
        src = SampleRate(SRC_SINC_BEST_QUALITY, channels)
        src.set_ratio(ratio)
        src.add_input_data(*cur_handle.read())
        new_data = src.get_output_data()
        new_length = len(new_data[0])

        # Write new sample
        new_handle = WavPackWMem(target_freq, channels, cur_is_float, cur_bits)
        if not cur_is_float:
            to_max = 2**(cur_bits - 1) - 1
            to_min = -to_max - 1
            mult = to_max
            for ch in new_data:
                for i in range(len(ch)):
                    ch[i] = min(max(to_min, int(ch[i] * mult)), to_max)
        new_handle.write(*new_data)
        raw_data = new_handle.get_contents()

        sample_data_key = self._get_full_sample_key(sample_id, 'p_sample.wv')

        new_header = self._get_sample_header(sample_id)
        new_header['freq'] = target_freq

        # Adjust loop bounds
        if new_length == 0:
            if 'loop_mode' in new_header:
                new_header['loop_mode'] = 'off'
        else:
            if 'loop_start' in new_header:
                target_start = int(round(new_header['loop_start'] * ratio))
                new_header['loop_start'] = min(max(0, target_start), new_length - 1)
            if 'loop_end' in new_header:
                cur_loop_start = new_header.get('loop_start', 0)
                target_end = int(round(new_header['loop_end'] * ratio))
                new_header['loop_end'] = min(max(
                    cur_loop_start + 1, target_end), new_length)

        sample_header_key = self._get_full_sample_key(sample_id, 'p_sh_sample.json')

        transaction = {}
        transaction[sample_header_key] = new_header
        transaction[sample_data_key] = raw_data

        self._store.put(transaction)
コード例 #2
0
    def get_task_post_loop_cut(self, sample_id, on_complete):
        # Get sample info
        header = self._get_sample_header(sample_id)
        assert header['loop_mode'] != 'off'
        assert header['loop_end'] > 0
        loop_end = header['loop_end']

        cur_handle = self._get_sample_data_handle(sample_id, convert_to_float=False)
        channels = cur_handle.get_channels()
        sample_length = cur_handle.get_length()
        use_float = cur_handle.is_float()
        bits = cur_handle.get_bits()
        assert loop_end < sample_length

        msg_fmt = 'Cutting sample data past loop end...'
        self._session.set_progress_description(msg_fmt)
        self._session.set_progress_position(0)
        self._updater.signal_update('signal_progress_start')
        yield

        # Copy sample data until loop end
        new_handle = WavPackWMem(cur_handle.get_audio_rate(), channels, use_float, bits)
        frames_left = loop_end
        cur_data = cur_handle.read(min(frames_left, 4096))
        while cur_data[0]:
            self._session.set_progress_position(
                    min(1, (loop_end - frames_left) / loop_end))
            self._updater.signal_update('signal_progress_step')
            yield

            if (not use_float) and (bits < 32):
                shift = 32 - bits
                for ch_num, ch in enumerate(cur_data):
                    for i in range(len(ch)):
                        ch[i] >>= shift

            new_handle.write(*cur_data)

            frames_left -= len(cur_data[0])
            cur_data = cur_handle.read(min(frames_left, 4096))

        self._session.set_progress_position(1)

        raw_data = new_handle.get_contents()
        sample_data_key = self._get_full_sample_key(sample_id, 'p_sample.wv')

        transaction = { sample_data_key: raw_data }

        def notifier(progress):
            if progress == 1:
                self._updater.signal_update('signal_progress_finished')
                on_complete()

        self._store.put(transaction, transaction_notifier=notifier)
コード例 #3
0
ファイル: sampleparams.py プロジェクト: kagu/kunquat
    def get_task_post_loop_cut(self, sample_id, on_complete):
        # Get sample info
        header = self._get_sample_header(sample_id)
        assert header['loop_mode'] != 'off'
        assert header['loop_end'] > 0
        loop_end = header['loop_end']

        cur_handle = self._get_sample_data_handle(sample_id, convert_to_float=False)
        channels = cur_handle.get_channels()
        sample_length = cur_handle.get_length()
        use_float = cur_handle.is_float()
        bits = cur_handle.get_bits()
        assert loop_end < sample_length

        msg_fmt = 'Cutting sample data past loop end...'
        self._session.set_progress_description(msg_fmt)
        self._session.set_progress_position(0)
        self._updater.signal_update('signal_progress_start')
        yield

        # Copy sample data until loop end
        new_handle = WavPackWMem(cur_handle.get_audio_rate(), channels, use_float, bits)
        frames_left = loop_end
        cur_data = cur_handle.read(min(frames_left, 4096))
        while cur_data[0]:
            self._session.set_progress_position(
                    min(1, (loop_end - frames_left) / loop_end))
            self._updater.signal_update('signal_progress_step')
            yield

            if (not use_float) and (bits < 32):
                shift = 32 - bits
                for ch_num, ch in enumerate(cur_data):
                    for i in range(len(ch)):
                        ch[i] >>= shift

            new_handle.write(*cur_data)

            frames_left -= len(cur_data[0])
            cur_data = cur_handle.read(min(frames_left, 4096))

        self._session.set_progress_position(1)

        raw_data = new_handle.get_contents()
        sample_data_key = self._get_full_sample_key(sample_id, 'p_sample.wv')

        transaction = { sample_data_key: raw_data }

        def notifier(progress):
            if progress == 1:
                self._updater.signal_update('signal_progress_finished')
                on_complete()

        self._store.put(transaction, transaction_notifier=notifier)
コード例 #4
0
    def _get_transaction_import_sample(self, sample_id, path):
        freq = 48000

        if path.endswith('.wv'):
            with open(path, 'rb') as f:
                sample_data = f.read()

            validator = WavPackValidator(sample_data)
            if not validator.is_data_valid():
                raise SampleImportError('Could not import {}:\n{}'.format(
                    path, validator.get_validation_error()))
            del validator

            wp = WavPackRMem(sample_data)
            freq = wp.get_audio_rate()

        else:
            try:
                sf = SndFileR(path, convert_to_float=False)
                sdata = list(sf.read())
            except SndFileError as e:
                raise SampleImportError('Could not import {}:\n{}'.format(path, str(e)))

            freq = sf.get_audio_rate()

            if sf.get_bits() < 32:
                rshift = 32 - sf.get_bits()
                for buf in sdata:
                    for i in range(len(buf)):
                        buf[i] >>= rshift
            wv = WavPackWMem(
                    sf.get_audio_rate(), sf.get_channels(), sf.is_float(), sf.get_bits())
            wv.write(*sdata)
            sample_data = wv.get_contents()

        format_exts = ('.wv', '.wav', '.au', '.flac')
        name = os.path.basename(path)
        if name.endswith(format_exts):
            name = name[:name.rfind('.')]

        sample_data_key = self._get_full_sample_key(sample_id, 'p_sample.wv')
        sample_header_key = self._get_full_sample_key(sample_id, 'p_sh_sample.json')
        sample_name_key = self._get_full_sample_key(sample_id, 'm_name.json')

        header = { 'format': 'WavPack', 'freq': freq, }

        transaction = {}
        transaction[sample_data_key] = sample_data
        transaction[sample_header_key] = header
        transaction[sample_name_key] = name

        return transaction
コード例 #5
0
    def _get_transaction_import_sample(self, sample_id, path):
        freq = 48000

        if path.endswith('.wv'):
            with open(path, 'rb') as f:
                sample_data = f.read()

            validator = WavPackValidator(sample_data)
            if not validator.is_data_valid():
                raise SampleImportError('Could not import {}:\n{}'.format(
                    path, validator.get_validation_error()))
            del validator

            wp = WavPackRMem(sample_data)
            freq = wp.get_audio_rate()

        else:
            try:
                sf = SndFileR(path, convert_to_float=False)
                sdata = list(sf.read())
            except SndFileError as e:
                raise SampleImportError('Could not import {}:\n{}'.format(path, str(e)))

            freq = sf.get_audio_rate()

            if sf.get_bits() < 32:
                rshift = 32 - sf.get_bits()
                for buf in sdata:
                    for i in range(len(buf)):
                        buf[i] >>= rshift
            wv = WavPackWMem(
                    sf.get_audio_rate(), sf.get_channels(), sf.is_float(), sf.get_bits())
            wv.write(*sdata)
            sample_data = wv.get_contents()

        format_exts = ('.wv', '.wav', '.au', '.flac')
        name = os.path.basename(path)
        if name.endswith(format_exts):
            name = name[:name.rfind('.')]

        sample_data_key = self._get_full_sample_key(sample_id, 'p_sample.wv')
        sample_header_key = self._get_full_sample_key(sample_id, 'p_sh_sample.json')
        sample_name_key = self._get_full_sample_key(sample_id, 'm_name.json')

        header = { 'format': 'WavPack', 'freq': freq, }

        transaction = {}
        transaction[sample_data_key] = sample_data
        transaction[sample_header_key] = header
        transaction[sample_name_key] = name

        return transaction
コード例 #6
0
    def get_task_create_xfade_loop_region(self, sample_id, xfade_length, on_complete):
        # Get sample info
        header = self._get_sample_header(sample_id)
        assert header['loop_mode'] == 'uni'
        loop_start = header['loop_start']
        loop_end = header['loop_end']
        loop_length = loop_end - loop_start

        assert xfade_length > 0
        assert xfade_length <= loop_length
        assert xfade_length <= loop_start

        cur_handle = self._get_sample_data_handle(sample_id, convert_to_float=False)
        channels = cur_handle.get_channels()
        sample_length = cur_handle.get_length()
        use_float = cur_handle.is_float()
        bits = cur_handle.get_bits()

        msg_fmt = 'Creating looping region...'
        self._session.set_progress_description(msg_fmt)
        self._session.set_progress_position(0)
        self._updater.signal_update('signal_progress_start')
        yield

        # Set up progress update helper
        step_count = 0
        total_step_count = 4
        if not use_float:
            total_step_count = 5

        def add_step():
            nonlocal step_count
            step_count += 1
            self._session.set_progress_position(min(1, step_count / total_step_count))
            self._updater.signal_update('signal_progress_step')
            yield

        # Get all sample data
        orig_data = cur_handle.read()

        yield from add_step()

        # Make copies of relevant sections
        init_length = loop_end - xfade_length
        init_data = [d[:init_length] for d in orig_data]
        fadeout_data = [d[init_length:loop_end] for d in orig_data]
        fadein_data = [d[loop_start - xfade_length:loop_start] for d in orig_data]
        trail_data = [d[loop_start:] for d in orig_data]
        assert len(fadeout_data[0]) == len(fadein_data[0])

        yield from add_step()

        # Create crossfaded section
        xfade_data = [[] for _ in orig_data]
        for ch in range(channels):
            fadein_ch = fadein_data[ch]
            fadeout_ch = fadeout_data[ch]
            for i, (in_item, out_item) in enumerate(zip(fadein_ch, fadeout_ch)):
                t = i / xfade_length
                diff = in_item - out_item
                xfade_item = out_item + t * diff
                xfade_data[ch].append(xfade_item)

        yield from add_step()

        # Scale integer contents
        if not use_float:
            shift = 32 - bits

            if shift > 0:
                for init_ch in init_data:
                    for i in range(len(init_ch)):
                        init_ch[i] >>= shift
                for trail_ch in trail_data:
                    for i in range(len(trail_ch)):
                        trail_ch[i] >>= shift

            val_max = 2**(bits - 1) - 1
            val_min = -val_max - 1
            for xfade_ch in xfade_data:
                for i in range(len(xfade_ch)):
                    shifted = int(xfade_ch[i]) >> shift
                    xfade_ch[i] = min(max(val_min, shifted), val_max)

            yield from add_step()

        # Write new sections
        new_handle = WavPackWMem(cur_handle.get_audio_rate(), channels, use_float, bits)
        new_handle.write(*init_data)
        new_handle.write(*xfade_data)
        new_handle.write(*trail_data)

        yield from add_step()

        raw_data = new_handle.get_contents()
        sample_data_key = self._get_full_sample_key(sample_id, 'p_sample.wv')

        transaction = { sample_data_key: raw_data }

        def notifier(progress):
            if progress == 1:
                self._updater.signal_update('signal_progress_finished')
                on_complete()

        self._store.put(transaction, transaction_notifier=notifier)
コード例 #7
0
    def get_task_convert_sample_format(
            self, sample_id, bits, use_float, normalise, on_complete):
        # Get current format parameters
        cur_handle = self._get_sample_data_handle(sample_id, convert_to_float=False)
        channels = cur_handle.get_channels()
        freq = cur_handle.get_audio_rate()
        cur_bits = cur_handle.get_bits()
        cur_is_float = cur_handle.is_float()
        sample_length = cur_handle.get_length()

        self._session.set_progress_description('Converting sample format...')
        self._session.set_progress_position(0)
        self._updater.signal_update('signal_progress_start')
        yield

        # Read sample data
        data = [[] for _ in range(channels)]
        chunk = cur_handle.read()
        while len(chunk[0]) > 0:
            for d, buf in zip(data, chunk):
                d.extend(buf)
            chunk = cur_handle.read()

        # Get conversion ratio and bounds
        from_max = 1 if cur_is_float else (2**31 - 1)
        to_max = 1 if use_float else (2**(bits - 1) - 1)
        to_min = -1 if use_float else (-to_max - 1)
        mult = to_max / from_max

        transaction = {}

        if normalise:
            # Normalise
            max_abs = 0
            for ch_num, ch in enumerate(data):
                for i, item in enumerate(ch):
                    if (i & 0x3fff) == 0:
                        self._session.set_progress_position(
                                ((ch_num + i / sample_length) / channels) * 0.5)
                        self._updater.signal_update('signal_progress_step')
                        yield

                    max_abs = max(max_abs, abs(item))

            norm_mult = from_max / max_abs
            if (norm_mult >= 1.01) or (norm_mult <= 0.99999):
                mult *= norm_mult

                # Adjust sample volume levels in note and hit maps
                shift_dB = -math.log(norm_mult, 2) * 6
                sample_num = self._get_sample_num(sample_id)

                note_map = self._get_note_map()
                for _, random_list in note_map:
                    for i, item in enumerate(random_list):
                        if item[0] == sample_num:
                            item[2] += shift_dB
                transaction[self._get_conf_key('p_nm_note_map.json')] = note_map

                hit_map = self._get_hit_map()
                for _, random_list in hit_map:
                    for i, item in enumerate(random_list):
                        if item[0] == sample_num:
                            item[2] += shift_dB
                transaction[self._get_conf_key('p_hm_hit_map.json')] = hit_map

        prog_phase_count = 2 if normalise else 1
        prog_start = prog_phase_count - 1
        self._session.set_progress_position(prog_start / prog_phase_count)

        # Write converted output
        new_handle = WavPackWMem(freq, channels, use_float, bits)
        if use_float:
            for ch_num, ch in enumerate(data):
                for i in range(len(ch)):
                    if (i & 0x3fff) == 0:
                        self._session.set_progress_position(
                                (prog_start + ((ch_num + i / sample_length) / channels)) /
                                prog_phase_count)
                        self._updater.signal_update('signal_progress_step')
                        yield

                    ch[i] *= mult
        else:
            for ch_num, ch in enumerate(data):
                for i in range(len(ch)):
                    if (i & 0x3fff) == 0:
                        self._session.set_progress_position(
                                (prog_start + ((ch_num + i / sample_length) / channels)) /
                                prog_phase_count)
                        self._updater.signal_update('signal_progress_step')
                        yield

                    ch[i] = min(max(to_min, int(ch[i] * mult)), to_max)

        new_handle.write(*data)
        raw_data = new_handle.get_contents()

        sample_data_key = self._get_full_sample_key(sample_id, 'p_sample.wv')

        transaction[sample_data_key] = raw_data

        def notifier(progress):
            if progress == 1:
                self._updater.signal_update('signal_progress_finished')
                on_complete()

        self._store.put(transaction, transaction_notifier=notifier)
コード例 #8
0
    def get_task_convert_sample_freq(self, sample_id, target_freq, on_complete):
        # Get current data and format info
        cur_handle = self._get_sample_data_handle(sample_id, convert_to_float=True)
        channels = cur_handle.get_channels()
        cur_freq = cur_handle.get_audio_rate()
        cur_bits, cur_is_float = self.get_sample_format(sample_id) # original format

        ratio = target_freq / cur_freq

        # Get converted audio data
        src = SampleRate(SRC_SINC_BEST_QUALITY, channels)
        src.set_ratio(ratio)

        self._session.set_progress_description('Resampling...')
        self._session.set_progress_position(0)
        self._updater.signal_update('signal_progress_start')
        est_length = int(cur_handle.get_length() * ratio)

        new_data = [[] for _ in range(channels)]
        cur_data = cur_handle.read(4096)
        while cur_data[0]:
            self._session.set_progress_position(min(1, len(new_data[0]) / est_length))
            self._updater.signal_update('signal_progress_step')
            yield

            next_data = cur_handle.read(4096)
            src.add_input_data(*cur_data, end_of_input=not bool(next_data[0]))
            resampled_chunk = src.get_output_data()
            for ch in range(channels):
                new_data[ch].extend(resampled_chunk[ch])
            cur_data = next_data

        new_length = len(new_data[0])

        self._session.set_progress_position(1)

        # Write new sample
        new_handle = WavPackWMem(target_freq, channels, cur_is_float, cur_bits)
        if not cur_is_float:
            to_max = 2**(cur_bits - 1) - 1
            to_min = -to_max - 1
            mult = to_max
            for ch in new_data:
                for i in range(len(ch)):
                    ch[i] = min(max(to_min, int(ch[i] * mult)), to_max)
        new_handle.write(*new_data)
        raw_data = new_handle.get_contents()

        sample_data_key = self._get_full_sample_key(sample_id, 'p_sample.wv')

        new_header = self._get_sample_header(sample_id)
        new_header['freq'] = target_freq

        # Adjust loop bounds
        if new_length == 0:
            if 'loop_mode' in new_header:
                new_header['loop_mode'] = 'off'
        else:
            if 'loop_start' in new_header:
                target_start = int(round(new_header['loop_start'] * ratio))
                new_header['loop_start'] = min(max(0, target_start), new_length - 1)
            if 'loop_end' in new_header:
                cur_loop_start = new_header.get('loop_start', 0)
                target_end = int(round(new_header['loop_end'] * ratio))
                new_header['loop_end'] = min(max(
                    cur_loop_start + 1, target_end), new_length)

        sample_header_key = self._get_full_sample_key(sample_id, 'p_sh_sample.json')

        transaction = {}
        transaction[sample_header_key] = new_header
        transaction[sample_data_key] = raw_data

        def notifier(progress):
            if progress == 1:
                self._updater.signal_update('signal_progress_finished')
                on_complete()

        self._store.put(transaction, transaction_notifier=notifier)
コード例 #9
0
    def convert_sample_format(self, sample_id, bits, use_float, normalise):
        # Get current format parameters
        cur_handle = self._get_sample_data_handle(sample_id, convert_to_float=False)
        channels = cur_handle.get_channels()
        freq = cur_handle.get_audio_rate()
        cur_bits = cur_handle.get_bits()
        cur_is_float = cur_handle.is_float()

        # Read sample data
        data = [[] for _ in range(channels)]
        chunk = cur_handle.read()
        while chunk[0]:
            for d, buf in zip(data, chunk):
                d.extend(buf)
            chunk = cur_handle.read()

        # Get conversion ratio and bounds
        from_max = 1 if cur_is_float else (2**31 - 1)
        to_max = 1 if use_float else (2**(bits - 1) - 1)
        to_min = -1 if use_float else (-to_max - 1)
        mult = to_max / from_max

        transaction = {}

        if normalise:
            # Normalise
            max_abs = 0
            for ch in data:
                for item in ch:
                    max_abs = max(max_abs, abs(item))

            norm_mult = from_max / max_abs
            if norm_mult >= 1.01:
                mult *= norm_mult

                # Adjust sample volume levels in note and hit maps
                shift_dB = -math.log(norm_mult, 2) * 6
                sample_num = self._get_sample_num(sample_id)

                note_map = self._get_note_map()
                for _, random_list in note_map:
                    for i, item in enumerate(random_list):
                        if item[0] == sample_num:
                            item[2] += shift_dB
                transaction[self._get_conf_key('p_nm_note_map.json')] = note_map

                hit_map = self._get_hit_map()
                for _, random_list in hit_map:
                    for i, item in enumerate(random_list):
                        if item[0] == sample_num:
                            item[2] += shift_dB
                transaction[self._get_conf_key('p_hm_hit_map.json')] = hit_map

        # Write converted output
        new_handle = WavPackWMem(freq, channels, use_float, bits)
        if use_float:
            for ch in data:
                for i in range(len(ch)):
                    ch[i] *= mult
        else:
            for ch in data:
                for i in range(len(ch)):
                    ch[i] = min(max(to_min, int(ch[i] * mult)), to_max)
        new_handle.write(*data)
        raw_data = new_handle.get_contents()

        sample_data_key = self._get_full_sample_key(sample_id, 'p_sample.wv')

        transaction[sample_data_key] = raw_data

        self._store.put(transaction)
コード例 #10
0
ファイル: sampleparams.py プロジェクト: kagu/kunquat
    def get_task_create_xfade_loop_region(self, sample_id, xfade_length, on_complete):
        free_sample_ids = self.get_free_sample_ids()
        if not free_sample_ids:
            raise RuntimeError('No free sample slots left')
        new_sample_id = free_sample_ids[0]

        # Get sample info
        header = self._get_sample_header(sample_id)
        assert header['loop_mode'] == 'uni'
        loop_start = header['loop_start']
        loop_end = header['loop_end']
        loop_length = loop_end - loop_start

        assert xfade_length > 0
        assert xfade_length <= loop_length
        assert xfade_length <= loop_start

        cur_handle = self._get_sample_data_handle(sample_id, convert_to_float=False)
        channels = cur_handle.get_channels()
        sample_length = cur_handle.get_length()
        use_float = cur_handle.is_float()
        bits = cur_handle.get_bits()

        msg_fmt = 'Creating looping region...'
        self._session.set_progress_description(msg_fmt)
        self._session.set_progress_position(0)
        self._updater.signal_update('signal_progress_start')
        yield

        # Set up progress update helper
        step_count = 0
        total_step_count = 4
        if not use_float:
            total_step_count = 5

        def add_step():
            nonlocal step_count
            step_count += 1
            self._session.set_progress_position(min(1, step_count / total_step_count))
            self._updater.signal_update('signal_progress_step')
            yield

        # Get all sample data
        orig_data = cur_handle.read()

        yield from add_step()

        # Make copies of relevant sections
        init_length = loop_end - xfade_length
        init_data = [d[:init_length] for d in orig_data]
        fadeout_data = [d[init_length:loop_end] for d in orig_data]
        fadein_data = [d[loop_start - xfade_length:loop_start] for d in orig_data]
        trail_data = [d[loop_start:] for d in orig_data]
        assert len(fadeout_data[0]) == len(fadein_data[0])

        yield from add_step()

        # Create crossfaded section
        xfade_data = [[] for _ in orig_data]
        for ch in range(channels):
            fadein_ch = fadein_data[ch]
            fadeout_ch = fadeout_data[ch]
            for i, (in_item, out_item) in enumerate(zip(fadein_ch, fadeout_ch)):
                t = i / xfade_length
                diff = in_item - out_item
                xfade_item = out_item + t * diff
                xfade_data[ch].append(xfade_item)

        yield from add_step()

        # Scale integer contents
        if not use_float:
            shift = 32 - bits

            if shift > 0:
                for init_ch in init_data:
                    for i in range(len(init_ch)):
                        init_ch[i] >>= shift
                for trail_ch in trail_data:
                    for i in range(len(trail_ch)):
                        trail_ch[i] >>= shift

            val_max = 2**(bits - 1) - 1
            val_min = -val_max - 1
            for xfade_ch in xfade_data:
                for i in range(len(xfade_ch)):
                    shifted = int(xfade_ch[i]) >> shift
                    xfade_ch[i] = min(max(val_min, shifted), val_max)

            yield from add_step()

        # Write new sections
        new_handle = WavPackWMem(cur_handle.get_audio_rate(), channels, use_float, bits)
        new_handle.write(*init_data)
        new_handle.write(*xfade_data)
        new_handle.write(*trail_data)

        yield from add_step()

        new_name_key = self._get_full_sample_key(new_sample_id, 'm_name.json')
        new_name = self.get_sample_name(sample_id) + ' – xfade'

        new_header = deepcopy(header)
        new_header_key = self._get_full_sample_key(new_sample_id, 'p_sh_sample.json')

        raw_data = new_handle.get_contents()
        sample_data_key = self._get_full_sample_key(new_sample_id, 'p_sample.wv')

        transaction = {
            new_name_key: new_name,
            new_header_key: new_header,
            sample_data_key: raw_data,
        }

        def notifier(progress):
            if progress == 1:
                self._updater.signal_update('signal_progress_finished')
                on_complete()

        self._store.put(transaction, transaction_notifier=notifier)
コード例 #11
0
ファイル: sampleparams.py プロジェクト: kagu/kunquat
    def get_task_convert_sample_format(
            self, sample_id, bits, use_float, normalise, on_complete):
        # Get current format parameters
        cur_handle = self._get_sample_data_handle(sample_id, convert_to_float=False)
        channels = cur_handle.get_channels()
        freq = cur_handle.get_audio_rate()
        cur_bits = cur_handle.get_bits()
        cur_is_float = cur_handle.is_float()
        sample_length = cur_handle.get_length()

        self._session.set_progress_description('Converting sample format...')
        self._session.set_progress_position(0)
        self._updater.signal_update('signal_progress_start')
        yield

        # Read sample data
        data = [[] for _ in range(channels)]
        chunk = cur_handle.read()
        while len(chunk[0]) > 0:
            for d, buf in zip(data, chunk):
                d.extend(buf)
            chunk = cur_handle.read()

        # Get conversion ratio and bounds
        from_max = 1 if cur_is_float else (2**31 - 1)
        to_max = 1 if use_float else (2**(bits - 1) - 1)
        to_min = -1 if use_float else (-to_max - 1)
        mult = to_max / from_max

        transaction = {}

        if normalise:
            # Normalise
            max_abs = 0
            for ch_num, ch in enumerate(data):
                for i, item in enumerate(ch):
                    if (i & 0x3fff) == 0:
                        self._session.set_progress_position(
                                ((ch_num + i / sample_length) / channels) * 0.5)
                        self._updater.signal_update('signal_progress_step')
                        yield

                    max_abs = max(max_abs, abs(item))

            norm_mult = from_max / max_abs
            if (norm_mult >= 1.01) or (norm_mult <= 0.99999):
                mult *= norm_mult

                # Adjust sample volume levels in note and hit maps
                shift_dB = -math.log(norm_mult, 2) * 6
                sample_num = self._get_sample_num(sample_id)

                note_map = self._get_note_map()
                for _, random_list in note_map:
                    for i, item in enumerate(random_list):
                        if item[0] == sample_num:
                            item[2] += shift_dB
                transaction[self._get_conf_key('p_nm_note_map.json')] = note_map

                hit_map = self._get_hit_map()
                for _, random_list in hit_map:
                    for i, item in enumerate(random_list):
                        if item[0] == sample_num:
                            item[2] += shift_dB
                transaction[self._get_conf_key('p_hm_hit_map.json')] = hit_map

        prog_phase_count = 2 if normalise else 1
        prog_start = prog_phase_count - 1
        self._session.set_progress_position(prog_start / prog_phase_count)

        # Write converted output
        new_handle = WavPackWMem(freq, channels, use_float, bits)
        if use_float:
            for ch_num, ch in enumerate(data):
                for i in range(len(ch)):
                    if (i & 0x3fff) == 0:
                        self._session.set_progress_position(
                                (prog_start + ((ch_num + i / sample_length) / channels)) /
                                prog_phase_count)
                        self._updater.signal_update('signal_progress_step')
                        yield

                    ch[i] *= mult
        else:
            for ch_num, ch in enumerate(data):
                for i in range(len(ch)):
                    if (i & 0x3fff) == 0:
                        self._session.set_progress_position(
                                (prog_start + ((ch_num + i / sample_length) / channels)) /
                                prog_phase_count)
                        self._updater.signal_update('signal_progress_step')
                        yield

                    ch[i] = min(max(to_min, int(ch[i] * mult)), to_max)

        new_handle.write(*data)
        raw_data = new_handle.get_contents()

        sample_data_key = self._get_full_sample_key(sample_id, 'p_sample.wv')

        transaction[sample_data_key] = raw_data

        def notifier(progress):
            if progress == 1:
                self._updater.signal_update('signal_progress_finished')
                on_complete()

        self._store.put(transaction, transaction_notifier=notifier)
コード例 #12
0
ファイル: sampleparams.py プロジェクト: kagu/kunquat
    def get_task_convert_sample_freq(self, sample_id, target_freq, on_complete):
        # Get current data and format info
        cur_handle = self._get_sample_data_handle(sample_id, convert_to_float=True)
        channels = cur_handle.get_channels()
        cur_freq = cur_handle.get_audio_rate()
        cur_bits, cur_is_float = self.get_sample_format(sample_id) # original format

        ratio = target_freq / cur_freq

        # Get converted audio data
        src = SampleRate(SRC_SINC_BEST_QUALITY, channels)
        src.set_ratio(ratio)

        self._session.set_progress_description('Resampling...')
        self._session.set_progress_position(0)
        self._updater.signal_update('signal_progress_start')
        est_length = int(cur_handle.get_length() * ratio)

        new_data = [[] for _ in range(channels)]
        cur_data = cur_handle.read(4096)
        while cur_data[0]:
            self._session.set_progress_position(min(1, len(new_data[0]) / est_length))
            self._updater.signal_update('signal_progress_step')
            yield

            next_data = cur_handle.read(4096)
            src.add_input_data(*cur_data, end_of_input=not bool(next_data[0]))
            resampled_chunk = src.get_output_data()
            for ch in range(channels):
                new_data[ch].extend(resampled_chunk[ch])
            cur_data = next_data

        new_length = len(new_data[0])

        self._session.set_progress_position(1)

        # Write new sample
        new_handle = WavPackWMem(target_freq, channels, cur_is_float, cur_bits)
        if not cur_is_float:
            to_max = 2**(cur_bits - 1) - 1
            to_min = -to_max - 1
            mult = to_max
            for ch in new_data:
                for i in range(len(ch)):
                    ch[i] = min(max(to_min, int(ch[i] * mult)), to_max)
        new_handle.write(*new_data)
        raw_data = new_handle.get_contents()

        sample_data_key = self._get_full_sample_key(sample_id, 'p_sample.wv')

        new_header = self._get_sample_header(sample_id)
        new_header['freq'] = target_freq

        # Adjust loop bounds
        if new_length == 0:
            if 'loop_mode' in new_header:
                new_header['loop_mode'] = 'off'
        else:
            if 'loop_start' in new_header:
                target_start = int(round(new_header['loop_start'] * ratio))
                new_header['loop_start'] = min(max(0, target_start), new_length - 1)
            if 'loop_end' in new_header:
                cur_loop_start = new_header.get('loop_start', 0)
                target_end = int(round(new_header['loop_end'] * ratio))
                new_header['loop_end'] = min(max(
                    cur_loop_start + 1, target_end), new_length)

        sample_header_key = self._get_full_sample_key(sample_id, 'p_sh_sample.json')

        transaction = {}
        transaction[sample_header_key] = new_header
        transaction[sample_data_key] = raw_data

        def notifier(progress):
            if progress == 1:
                self._updater.signal_update('signal_progress_finished')
                on_complete()

        self._store.put(transaction, transaction_notifier=notifier)