diff --git a/Oe2sSLE_GUI.py b/Oe2sSLE_GUI.py index d782834..0791c02 100755 --- a/Oe2sSLE_GUI.py +++ b/Oe2sSLE_GUI.py @@ -33,6 +33,7 @@ import RIFF import e2s_sample_all as e2s from VerticalScrolledFrame import VerticalScrolledFrame +import wav_tools import os.path @@ -1862,6 +1863,7 @@ def fct(): def import_sample(self): filenames = tk.filedialog.askopenfilenames(parent=self.root,title="Select WAV file(s) to import",filetypes=(('Wav Files','*.wav'), ('All Files','*.*'))) def fct(): + converted = [[],[]] # (8 bits, 24 bits) for filename in filenames: try: with open(filename, 'rb') as f: @@ -1883,11 +1885,21 @@ def fct(): continue if fmt.bitPerSample != 16: - tk.messagebox.showwarning( - "Import WAV", - "Cannot use this file:\n{}\nWAV format must use 16 bits per sample.\nConvert it before importing it.".format(filename) - ) - continue + if fmt.bitPerSample == 8: + wav_tools.wav_pcm_8b_to_16b(sample) + converted[0] += [filename] + elif fmt.bitPerSample == 24: + wav_tools.wav_pcm_24b_to_16b(sample) + converted[1] += [filename] + else: + tk.messagebox.showwarning( + "Import WAV", + "Cannot use this file:\n{}\nWAV format must preferably use 16 bits per sample.\n" + + "8 bits and old 24 bits per sample are also supported but will be converted to 16 bits.\n" + "Convert your file before importing it.".format(filename) + ) + continue + fmt = sample.get_fmt() if not sample.RIFF.chunkList.get_chunk(b'korg'): korg_data=e2s.RIFF_korg() @@ -1969,7 +1981,13 @@ def fct(): "Cannot use this file:\n{}\nToo many samples.".format(filename) ) break - + if not all(n_conv == [] for n_conv in converted): + tk.messagebox.showinfo( + "Import WAV", + ("{} file(s) converted from 8 bits to 16 bits.\n".format(len(converted[0])) if len(converted[0]) else "") + + ("{} file(s) converted from 24 bits to 16 bits.\n".format(len(converted[1])) if len(converted[1]) else "") + ) + wd = WaitDialog(self.root) wd.run(fct) diff --git a/RIFF/__init__.py b/RIFF/__init__.py index 072c7b5..ff7160b 100755 --- a/RIFF/__init__.py +++ b/RIFF/__init__.py @@ -101,8 +101,11 @@ def read(self, file, **kw): if len(self.data)&1: file.read(1) - def write(self, file): + def update_header(self): self.header.size = len(self.data) + + def write(self, file): + self.update_header() self.header.write(file) self.data.write(file) # align to word size diff --git a/e2s_sample_all.py b/e2s_sample_all.py index d0e7183..732b001 100755 --- a/e2s_sample_all.py +++ b/e2s_sample_all.py @@ -352,6 +352,7 @@ def read(self, file): self.RIFF = RIFF.Form(file,self.header,registeredForms={b'WAVE':RIFF_korgWAVEChunkList}) def write(self, file): + self.update_header() self.header.write(file) self.RIFF.write(file) @@ -364,6 +365,14 @@ def get_data(self): def get_fmt(self): return self.RIFF.chunkList.get_chunk(b'fmt ').data + def get_chunk(self, id): + return self.RIFF.chunkList.get_chunk(id) + + + def update_header(self): + self.header.size = len(self.RIFF) + + def get_clean_copy(self): copy = e2s_sample() copy.header = RIFF.ChunkHeader(id=self.header.id) diff --git a/wav_tools.py b/wav_tools.py new file mode 100644 index 0000000..8d5cacf --- /dev/null +++ b/wav_tools.py @@ -0,0 +1,71 @@ +# -*- coding: utf-8 -*- +""" +Copyright (C) 2016 Jonathan Taquet + +This file is part of Oe2sSLE (Open e2sSample.all Library Editor). + +Foobar is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Foobar is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Oe2sSLE. If not, see +""" + +import RIFF +import e2s_sample_all + +import struct + +def wav_pcm_8b_to_16b(e2s_sample): + # checks + fmt = e2s_sample.get_fmt() + if ( fmt.formatTag != fmt.WAVE_FORMAT_PCM + or fmt.bitPerSample != 8): + return None + in_data = e2s_sample.get_data().rawdata + n_samples = len(in_data) + + sample_values=struct.unpack(str(n_samples)+'B', in_data) + w_sample_values=[(i - 128)*256 for i in sample_values] + data=struct.pack('<'+str(n_samples)+'h',*w_sample_values) + + e2s_sample.get_chunk(b'data').data.rawdata = data + e2s_sample.get_chunk(b'data').update_header() + e2s_sample.update_header() + fmt.bitPerSample = 16 + fmt.avgBytesPerSec *= 2 + fmt.blockAlign *= 2 + + # TODO: update cue points chunkStart and blockStart if used later + + return e2s_sample + +def wav_pcm_24b_to_16b(e2s_sample): + # checks + fmt = e2s_sample.get_fmt() + if ( fmt.formatTag != fmt.WAVE_FORMAT_PCM + or fmt.bitPerSample != 24): + return None + in_data=e2s_sample.get_data().rawdata + n_samples = len(in_data)//3 + + data=bytes([in_data[b] for i in range(n_samples) for b in (i*3+1, i*3+2)]) + + e2s_sample.get_chunk(b'data').data.rawdata = data + e2s_sample.get_chunk(b'data').update_header() + e2s_sample.update_header() + fmt.bitPerSample = 16 + fmt.avgBytesPerSec = fmt.avgBytesPerSec * 2 // 3 + fmt.blockAlign = fmt.blockAlign * 2 // 3 + + # TODO: update cue points chunkStart and blockStart if used later + + return e2s_sample + \ No newline at end of file