Skip to content

Commit

Permalink
add ability to import 8bits and 24bits wav samples
Browse files Browse the repository at this point in the history
- allow to import standard 8bits pcm samples.
- allow to import old format for 24bits pcm samples (still widely used).
  • Loading branch information
JonathanTaquet committed Jun 26, 2016
1 parent 6695025 commit 56cbaf0
Show file tree
Hide file tree
Showing 4 changed files with 108 additions and 7 deletions.
30 changes: 24 additions & 6 deletions Oe2sSLE_GUI.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import RIFF
import e2s_sample_all as e2s
from VerticalScrolledFrame import VerticalScrolledFrame
import wav_tools

import os.path

Expand Down Expand Up @@ -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:
Expand All @@ -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()
Expand Down Expand Up @@ -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)

Expand Down
5 changes: 4 additions & 1 deletion RIFF/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
9 changes: 9 additions & 0 deletions e2s_sample_all.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand All @@ -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)
Expand Down
71 changes: 71 additions & 0 deletions wav_tools.py
Original file line number Diff line number Diff line change
@@ -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 <http://www.gnu.org/licenses/>
"""

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

0 comments on commit 56cbaf0

Please sign in to comment.