Exemplo n.º 1
0
 def read(self, file):
     self.header = RIFF.ChunkHeader(file)
     # now, parse
     if self.header.id != b"RIFF":
         raise ValueError("Expected {} chunk, got {}; ignored.".format(
             b"RIFF", self.header.id))
     self.RIFF = RIFF.Form(
         file,
         self.header,
         registeredForms={b'WAVE': RIFF_korgWAVEChunkList})
Exemplo n.º 2
0
    def get_clean_copy(self):
        from copy import deepcopy
        copy = e2s_sample()
        copy.header = RIFF.ChunkHeader(id=self.header.id)
        copy.RIFF.chunkList.chunks.append(
            deepcopy(self.RIFF.chunkList.get_chunk(b'fmt ')))
        # if "fmt " chunk contains extra data they are removed
        copy.RIFF.chunkList.chunks[-1].data.otherFieldsRAW = None

        copy.RIFF.chunkList.chunks.append(
            self.RIFF.chunkList.get_chunk(b'data'))
        copy.RIFF.chunkList.chunks.append(
            self.RIFF.chunkList.get_chunk(b'korg'))
        copy.header.size = len(copy.RIFF)
        return copy
Exemplo n.º 3
0
class RIFF_korg_esli(RIFF.ChunkData):
    _dataSize = 1172
    _chunkHeader = RIFF.ChunkHeader(id=b'esli', size=_dataSize)

    class SliceData:
        def __init__(self, esli_master, slice_num):
            self.__dict__['fields'] = dict()
            self.__dict__['esli'] = esli_master
            offset = self.esli.fields['slicesData'][
                0] + slice_num * struct.calcsize('4I')
            self.fields['start'] = (offset, '<i')
            offset += struct.calcsize('I')
            self.fields['length'] = (offset, '<I')
            offset += struct.calcsize('I')
            self.fields['attack_length'] = (offset, '<I')
            offset += struct.calcsize('I')
            self.fields['amplitude'] = (offset, '<I')
            offset += struct.calcsize('I')

        def __getattr__(self, name):
            try:
                loc, fmt = self.fields[name]
            except:
                raise AttributeError
            else:
                size = struct.calcsize(fmt)
                unpacked = struct.unpack(fmt,
                                         self.esli.rawdata[loc:loc + size])
                if len(unpacked) == 1:
                    return unpacked[0]
                else:
                    return unpacked

        def __setattr__(self, name, value):
            try:
                loc, fmt = self.fields[name]
            except:
                self.__dict__[name] = value
            else:
                size = struct.calcsize(fmt)
                self.__dict__['esli'].rawdata[loc:loc + size] = struct.pack(
                    fmt, value)

    class SliceSteps:
        def __init__(self, esli_master):
            self.esli = esli_master
            self.baseOffset = self.esli.fields['slicesActiveSteps'][0]

        def __getitem__(self, index):
            assert index >= 0 and index < 64
            return struct.unpack(
                'b', self.esli.rawdata[self.baseOffset +
                                       index:self.baseOffset + index + 1])[0]

        def __setitem__(self, index, value):
            assert index >= 0 and index < 64
            self.esli.rawdata[self.baseOffset + index:self.baseOffset + index +
                              1] = struct.pack('b', value)

    def __init__(self, file=None, chunkHeader=None):
        self.__dict__['fields'] = dict()
        self.__dict__['rawdata'] = bytearray(RIFF_korg_esli._dataSize)
        offset = 0
        self.fields['OSC_0index'] = (offset, '<H')
        offset += struct.calcsize('H')
        self.fields['OSC_name'] = (offset, '16s')
        offset += struct.calcsize('16s')
        self.fields['OSC_category'] = (offset, '<H')
        offset += struct.calcsize('H')
        self.fields['OSC_importNum'] = (offset, '<H')
        offset += struct.calcsize('H')
        self.fields['_16_22_UFix'] = (offset, '12s')
        offset += struct.calcsize('12s')
        self.fields['playLogPeriod'] = (offset, '<H')
        offset += struct.calcsize('<H')
        self.fields['playVolume'] = (offset, '<H')
        offset += struct.calcsize('<H')
        self.fields['_26_UVar'] = (offset, '1s')
        offset += struct.calcsize('1s')
        self.fields['_27_UFix'] = (offset, '1s')
        offset += struct.calcsize('1s')
        self.fields['OSC_StartPoint_address'] = (offset, '<I')
        offset += struct.calcsize('I')
        self.fields['OSC_LoopStartPoint_offset'] = (offset, '<I')
        offset += struct.calcsize('I')
        self.fields['OSC_EndPoint_offset'] = (offset, '<I')
        offset += struct.calcsize('I')
        self.fields['OSC_OneShot'] = (offset, '?')
        offset += struct.calcsize('?')
        self.fields['_35_3C_UFix'] = (offset, '7s')
        offset += struct.calcsize('7s')
        self.fields['WAV_dataSize'] = (offset, '<I')
        offset += struct.calcsize('I')
        self.fields['useChan0_UFix'] = (offset, 'B')
        offset += struct.calcsize('B')
        self.fields['useChan1'] = (offset, '?')
        offset += struct.calcsize('?')
        self.fields['playLevel12dB'] = (offset, '?')
        offset += struct.calcsize('?')
        self.fields['_43_48_UFix'] = (offset, '5s')
        offset += struct.calcsize('5s')
        self.fields['samplingFreq'] = (offset, '<I')
        offset += struct.calcsize('I')
        self.fields['_4C_UFix'] = (offset, '1s')
        offset += struct.calcsize('1s')
        self.fields['sampleTune'] = (offset, '<b')
        offset += struct.calcsize('b')
        self.fields['OSC_0index1'] = (offset, '<H')
        offset += struct.calcsize('H')
        self.fields['slicesData'] = (offset, '<256I')
        offset += struct.calcsize('256I')
        self.fields['slicesActiveSteps'] = (offset, '64s')
        offset += struct.calcsize('64s')
        self.fields['slicingNumSteps'] = (offset, 'B')
        offset += struct.calcsize('B')
        self.fields['slicingBeat'] = (offset, 'B')
        offset += struct.calcsize('B')
        self.fields['slicesNumActiveSteps'] = (offset, 'B')
        offset += struct.calcsize('B')
        self.fields['_493_UVar'] = (offset, '1s')
        offset += struct.calcsize('1s')

        self.__dict__['slices'] = []
        for i in range(64):
            self.slices.append(self.SliceData(self, i))

        self.__dict__['sliceSteps'] = self.SliceSteps(self)

        if file:
            self.read(file, chunkHeader)
        else:
            self.reset()

    def __len__(self):
        return RIFF_korg_esli._dataSize

    def __getattr__(self, name):
        try:
            loc, fmt = self.fields[name]
        except:
            raise AttributeError
        else:
            size = struct.calcsize(fmt)
            unpacked = struct.unpack(fmt, self.rawdata[loc:loc + size])
            if len(unpacked) == 1:
                return unpacked[0]
            else:
                return unpacked

    def __setattr__(self, name, value):
        try:
            loc, fmt = self.fields[name]
        except:
            self.__dict__[name] = value
        else:
            size = struct.calcsize(fmt)
            self.__dict__['rawdata'][loc:loc + size] = struct.pack(fmt, value)

    def read(self, file, chunkHeader):
        if chunkHeader.id != b'esli':
            raise TypeError("'elsi' chunk expected")
        if chunkHeader.size < RIFF_korg_esli._dataSize:
            raise ValueError('Unknown esli chunck size')
        if chunkHeader.size > RIFF_korg_esli._dataSize:
            print('Unusual esli chunck size')
        self.rawdata[:] = file.read(chunkHeader.size)
        if len(self.rawdata) != chunkHeader.size:
            raise EOFError('Unexpected End Of File')

        if self._16_22_UFix != b'\x00\x00\x00\x7F\x00\x01\x00\x00\x00\x00\x00\x00':
            print('Unusual values in _16_22_UFix: ', self._16_22_UFix)
        if self._27_UFix != b'\x00':
            print('Unusual values in _27_UFix: ', self._27_UFix)
        if self._35_3C_UFix != b'\x00\x00\x00\x00\x00\x00\x00':
            print('Unusual values in _35_3C_UFix: ', self._35_3C_UFix)
        if self._43_48_UFix != b'\x01\xB0\x04\x00\x00':
            print('Unusual values in _43_48_UFix: ', self._43_48_UFix)
        if self._4C_UFix != b'\x00':
            print('Unusual values in _4C_UFix: ', self._4C_UFix)
        if self.useChan0_UFix != 1:
            print('Unusual value in useChan0_UFix: ', self.useChan0_UFix)

    def reset(self):
        self._16_22_UFix = b'\x00\x00\x00\x7F\x00\x01\x00\x00\x00\x00\x00\x00'
        self._27_UFix = b'\x00'
        self._35_3C_UFix = b'\x00\x00\x00\x00\x00\x00\x00'
        self._43_48_UFix = b'\x01\xB0\x04\x00\x00'
        self._4C_UFix = b'\x00'
        self.useChan0_UFix = 1

        self.OSC_category = OSC.USER
        self.OSC_OneShot = True

    def get_chunk_header(self):
        return RIFF_korg_esli._chunkHeader

    def write(self, file):
        file.write(self.rawdata)

    def set_OSCNum(self, num):
        self.OSC_0index = self.OSC_0index1 = num - 1

    def get_OSCNum(self):
        return self.OSC_0index + 1
Exemplo n.º 4
0
    def write(self, file, export_smpl=False, export_cue=False, _do_clean=True):
        sample = self

        if _do_clean:
            sample = self.get_clean_copy()

        esli = sample.get_esli()
        fmt = sample.get_fmt()
        uid = 0

        if export_smpl and esli.OSC_LoopStartPoint_offset < esli.OSC_EndPoint_offset:
            smpl = RIFF_smpl()
            smpl.samplePeriod = int(round(1. / esli.samplingFreq * 10.**9))
            loop = smpl.add_loop()
            loop.identifier = uid  # not adding a cue point for the loop
            #loop.type = 0 # loop forward
            loop.start = (esli.OSC_StartPoint_address +
                          esli.OSC_LoopStartPoint_offset) // fmt.blockAlign
            loop.end = (esli.OSC_StartPoint_address +
                        esli.OSC_EndPoint_offset) // fmt.blockAlign
            #loop.fraction = 0
            #loop.playCount = 0 # infinite loop
            smpl_chunk = RIFF.Chunk(header=RIFF.ChunkHeader(id=b'smpl'),
                                    data=smpl)
            sample.RIFF.chunkList.chunks.append(smpl_chunk)
            uid += 1

        if export_cue:
            num_samples = len(sample.get_data()) // fmt.blockAlign
            start_sample = esli.OSC_StartPoint_address // fmt.blockAlign
            slices = []
            for slice in esli.slices:
                if not slice.length:
                    continue
                if slice.start >= num_samples:
                    continue
                # remove duplicates
                skip = False
                for other in slices:
                    if slice.start == other.start:
                        skip = True
                        break
                if skip:
                    continue
                slices.append(slice)
            if slices:
                cue = RIFF_cue()
                for slice in slices:
                    cue_point = cue.add_cue_point()
                    cue_point.identifier = uid
                    cue_point.position = slice.start + start_sample
                    cue_point.fccChunk = b'data'
                    #cue_point.chunkStart = 0
                    #cue_point.blockStart = 0
                    cue_point.sampleOffset = slice.start + start_sample
                    uid += 1
                cue_chunk = RIFF.Chunk(header=RIFF.ChunkHeader(id=b'cue '),
                                       data=cue)
                sample.RIFF.chunkList.chunks.append(cue_chunk)

        sample.update_header()
        sample.header.write(file)
        sample.RIFF.write(file)
Exemplo n.º 5
0
 def __init__(self, file=None, **kw):
     if file:
         self.read(file)
     else:
         self.RIFF = RIFF.Form(type=b'WAVE',
                               chunkList=RIFF_korgWAVEChunkList())
Exemplo n.º 6
0
 def __init__(self, file=None, chunkHeader=None):
     self.chunkList = RIFF.ChunkList(RIFF_korg.registeredChunks)
     if file:
         self.read(file, chunkHeader)
Exemplo n.º 7
0
def from_wav(filename, import_opts=ImportOptions()):
    converted_from = None
    with open(filename, 'rb') as f:
        sample = e2s.e2s_sample(f)
    # check format
    fmt = sample.get_fmt()
    if fmt.formatTag != fmt.WAVE_FORMAT_PCM:
        raise NotWaveFormatPcm
    # electribe and Oe2sSLE do not allow empty samples
    if not len(sample.get_data()):
        raise EmptyWav
    if fmt.bitPerSample != 16:
        if fmt.bitPerSample == 8:
            wav_tools.wav_pcm_8b_to_16b(sample)
            converted_from = 8
        elif fmt.bitPerSample == 24:
            wav_tools.wav_pcm_24b_to_16b(sample)
            converted_from = 24
        else:
            raise NotSupportedBitPerSample
        fmt = sample.get_fmt()

    if not sample.RIFF.chunkList.get_chunk(b'korg'):
        korg_data = e2s.RIFF_korg()
        korg_chunk = RIFF.Chunk(header=RIFF.ChunkHeader(id=b'korg'),
                                data=korg_data)
        sample.RIFF.chunkList.chunks.append(korg_chunk)
        sample.header.size += len(korg_chunk)

    korg_chunk = sample.RIFF.chunkList.get_chunk(b'korg')

    esli_chunk = korg_chunk.data.chunkList.get_chunk(b'esli')
    if not esli_chunk:
        esli = e2s.RIFF_korg_esli()
        esli_chunk = RIFF.Chunk(header=RIFF.ChunkHeader(id=b'esli'), data=esli)
        korg_chunk.data.chunkList.chunks.append(esli_chunk)
        esli.OSC_name = bytes(
            os.path.splitext(os.path.basename(filename))[0], 'ascii', 'ignore')
        # todo funtion for that:
        data = sample.get_data()
        esli.samplingFreq = fmt.samplesPerSec
        esli.OSC_EndPoint_offset = esli.OSC_LoopStartPoint_offset = len(
            data) - fmt.blockAlign
        esli.WAV_dataSize = len(data)
        if fmt.blockAlign == 4:
            # stereo
            esli.useChan1 = True
        # by default use maximum volume
        # unlike electribe which normalizes volume
        esli.playVolume = 65535

        # use options defaults
        esli.OSC_category = esli.OSC_category = e2s.esli_str_to_OSC_cat[
            import_opts.osc_cat]
        esli.playLevel12dB = import_opts.plus_12_db

        esli.OSC_importNum = ImportOptions.import_num
        ImportOptions.import_num += 1
        # by default play speed is same as indicated by Frequency
        esli.playLogPeriod = 65535 if fmt.samplesPerSec == 0 else max(
            0, int(round(63132 - math.log2(fmt.samplesPerSec) * 3072)))
        esli_chunk.header.size += len(esli_chunk)
        sample.header.size += len(esli_chunk)

        # check if smpl chunk is used
        smpl_chunk = sample.RIFF.chunkList.get_chunk(b'smpl')
        smpl_used = False
        if smpl_chunk:
            # use it to initialize loop point
            if smpl_chunk.data.numSampleLoops > 0:
                # todo: if several LoopData, propose to generate several wavs ?
                smpl_loop = smpl_chunk.data.loops[0]
                if smpl_loop.playCount != 1:
                    # looping sample
                    start = smpl_loop.start * fmt.blockAlign
                    end = smpl_loop.end * fmt.blockAlign
                    if start < end and end <= len(data) - fmt.blockAlign:
                        esli.OSC_LoopStartPoint_offset = start - esli.OSC_StartPoint_address
                        esli.OSC_OneShot = 0
                        esli.OSC_EndPoint_offset = end - esli.OSC_StartPoint_address
                        smpl_used = True
        if not smpl_used and import_opts.loop_type == 1:
            # loop all
            esli.OSC_LoopStartPoint_offset = 0
            esli.OSC_OneShot = 0
        # check if cue chunk is used
        cue_chunk = sample.RIFF.chunkList.get_chunk(b'cue ')
        if cue_chunk:
            num_samples = len(data) // fmt.blockAlign
            cue_points = []
            for cue_point in cue_chunk.data.cuePoints:
                if cue_point.fccChunk != b'data' or cue_point.sampleOffset >= num_samples:
                    # unhandled cue_point
                    continue
                else:
                    cue_points.append(cue_point)
            start_sample = esli.OSC_StartPoint_address // fmt.blockAlign
            num_slices = 0
            cue_points.sort(key=lambda cue_point: cue_point.sampleOffset)
            for cue_point in cue_points:
                if num_slices >= 64:
                    break
                else:
                    esli.slices[
                        num_slices].start = cue_point.sampleOffset - start_sample
                    esli.slices[
                        num_slices].length = num_samples - cue_point.sampleOffset
                    if num_slices > 0:
                        esli.slices[num_slices - 1].length = esli.slices[
                            num_slices].start - esli.slices[num_slices -
                                                            1].start
                    num_slices += 1

    else:
        esli = esli_chunk.data

    converted_to_mono = apply_forced_options(sample, import_opts)
    return sample, converted_from, converted_to_mono