diff -ur v11/snddiv.py v12/snddiv.py --- v11/snddiv.py 2020-02-01 12:36:25.000000000 +0900 +++ v12/snddiv.py 2020-09-23 20:59:26.000000000 +0900 @@ -1,155 +1,27 @@ #!/usr/bin/env python import sys -import os -import time -import yaml -import select -import threading import empty import cmd_ut import thr import io_ut +import snd_ut import dbg import arg -silent = False - -def data_new(name_mp3): - - (name, mp3) = os.path.splitext(name_mp3) - - def make_wav(): - if os.path.exists( name + '.wav' ): - return - if not os.path.exists( name_mp3 ): - dbg.err_exit( 'not found {}'.format(name_mp3) ) - cmd = 'lame --decode {} > /dev/null 2>&1'.format( name_mp3 ) - dbg.out('make {}.wav ... '.format(name), '') - cmd_ut.call(cmd) - dbg.out('OK') - - def raw_opt_new(): - cmd = 'sox --info {}.wav'.format(name) - s = cmd_ut.call(cmd) - d = yaml.load(s) - - r = float( d.get('Sample Rate', 44100) ) - - b = 16 - s = d.get('Precision') - if s.endswith('-bit'): - b = int( s[:-len('-bit')] ) - - c = int( d.get('Channels', 2) ) - - e = 'signed-integer' - s = d.get('Sample Encoding', 'Signed') - if 'Signed' not in s: - e = 'unsigned-interger' - - get_raw_opt = lambda r_rate=1.0: '-t raw -r {} -b {} -c {} -e {}'.format(r*r_rate, b, c, e) - - byte_per_smp = c * (b//8) - smp_sec = lambda sec: int( sec * r ) - smp_to_sec = lambda m: m / r - byte_sec = lambda sec: smp_sec(sec) * byte_per_smp - byte_to_sec = lambda n: smp_to_sec( n // byte_per_smp ) - - return empty.new( locals() ) - - def make_raw(): - if os.path.exists( name + '.raw' ): - return - cmd = 'sox {}.wav {}.raw'.format(name, name) - dbg.out('make {}.raw ... '.format(name), '') - cmd_ut.call(cmd) - dbg.out('OK') - - make_wav() - opt = raw_opt_new() - make_raw() - - dat = bytes([]) - with open( '{}.raw'.format(name), 'rb' ) as f: - dat = f.read() - - n = opt.byte_per_smp - m = len(dat) // n - - dbg.out('make smp_lst ... ', '') - smp_lst = list( map( lambda i: dat[i*n:i*n+n], range(m) ) ) - smp_rlst = smp_lst[::-1] - dbg.out('OK') - - def get_smp_sec(sec, reverse): - m = opt.smp_sec(sec) - return smp_rlst[-m:] if reverse else smp_lst[m:] - - def get_dat_sec(sec, reverse, shift=0): - lst = get_smp_sec(sec, reverse) - if shift > 0: - lst = lst[:: 2**shift ] - return b''.join(lst) - - def get_smp_from_to(sec_f, sec_t): - f = opt.smp_sec(sec_f) - t = opt.smp_sec(sec_t) - return smp_lst[f:t] - - def get_dat_from_to(sec_f, sec_t): - lst = get_smp_from_to(sec_f, sec_t) - return b''.join(lst) - - def save(sec_f, sec_t, name, dbg_out): - (name, ext) = os.path.splitext(name) - if not ext or ext not in ('raw', 'wav', 'mp3'): - ext = 'mp3' - - dbg_out('save {}.raw ... '.format(name), '') - dat = get_dat_from_to(sec_f, sec_t) - with open( '{}.raw'.format(name), 'wb' ) as f: - f.write(dat) - dbg_out('OK') - if ext == 'raw': - return - - dbg_out('save {}.wav ... '.format(name), '') - cmd = 'sox {} {}.raw {}.wav'.format( opt.get_raw_opt(), name, name ) - cmd_ut.call(cmd) - dbg_out('OK') - if ext == 'wav': - cmd = 'rm -f {}.raw'.format(name) - cmd_ut.call(cmd) - dbg_out('delete {}.raw'.format(name)) - return - - dbg_out('save {}.mp3 ... '.format(name), '') - cmd = 'lame {}.wav {}.mp3 > /dev/null 2>&1'.format( name, name ) - cmd_ut.call(cmd) - dbg_out('OK') - cmd = 'rm -f {}.raw {}.wav'.format( name, name ) - cmd_ut.call(cmd) - dbg_out('delete {}.raw'.format(name)) - dbg_out('delete {}.wav'.format(name)) - - last_sec = opt.byte_to_sec( len(dat) ) - - return empty.new( locals() ) - -def play_new(dat, opt, sudo_passwd='', r_rate=1.0): +def play_new(dat, inf, sudo_passwd='', r_rate=1.0): e = empty.new() e.dat = dat e.run = False e.sec = 0 e.rbuf = '' - e.evt = threading.Event() + e.evt = thr.event_new() - last_sec = opt.byte_to_sec( len(dat) ) + last_sec = inf.byte_to_sec( len(dat) ) def proc_new(): - cmd = 'play {} -'.format( opt.get_raw_opt(r_rate) ) + cmd = 'play {} -'.format( inf.get_raw_opt(r_rate) ) PIPE = cmd_ut.PIPE proc = cmd_ut.proc_new(cmd, stdin=PIPE, stdout=PIPE, stderr=PIPE, sudo_pw=sudo_passwd) return proc @@ -204,8 +76,15 @@ return empty.to_attr( e, locals() ) -def snd_new(data, sudo_passwd, dbg_out): - opt = data.opt +def snd_new(data, sudo_passwd): + inf = data.inf + last_sec = inf.smp_to_sec( inf.smp_n ) + dbg.out( 'last_sec={}'.format( last_sec ) ) + + b = data.get_bytes() + n = inf.byte_per_smp + smp_lst = list( map( lambda i: b[i*n:i*n+n], range( inf.smp_n ) ) ) + smp_rlst = smp_lst[::-1] e = empty.new() e.sec = 0 @@ -213,7 +92,26 @@ e.reverse = False e.shift = 0 - divs = [ 0, data.last_sec ] + divs = [ 0, last_sec ] + + def get_smp_sec(sec, reverse): + m = inf.smp_sec(sec) + return smp_rlst[-m:] if reverse else smp_lst[m:] + + def get_dat_sec(sec, reverse, shift=0): + lst = get_smp_sec(sec, reverse) + if shift > 0: + lst = lst[:: 2**shift ] + return b''.join(lst) + + def get_smp_from_to(sec_f, sec_t): + f = inf.smp_sec(sec_f) + t = inf.smp_sec(sec_t) + return smp_lst[f:t] + + def get_dat_from_to(sec_f, sec_t): + lst = get_smp_from_to(sec_f, sec_t) + return b''.join(lst) def get_sec(): add = 0 @@ -226,8 +124,10 @@ def start(): if e.play: stop() - dat = data.get_dat_sec( e.sec, e.reverse, max(e.shift, 0) ) - e.play = play_new( dat, opt, sudo_passwd, min(2**e.shift, 1.0) ) + + dat = get_dat_sec( e.sec, e.reverse, max(e.shift, 0) ) + + e.play = play_new( dat, inf, sudo_passwd, min(2**e.shift, 1.0) ) e.play.start() def stop(): @@ -274,7 +174,8 @@ def save(i, name): if 0 <= i and i < len(divs)-1: - data.save( divs[i], divs[i+1], name, dbg_out ) + dat = get_dat_from_to( divs[ i ], divs[ i + 1 ] ) + data.save_bytes_to( dat, name ) dbg.out('OK') def curr_area(): @@ -304,14 +205,14 @@ silent = a.is_pop('-silent') filename_mp3 = a.pop() if not filename_mp3: - dbg.err_exit( 'Usage: {} [-g] [-S sudo_passwd] [-silent] filename_mp3'.format( sys.argv[0] ) ) + dbg.help_exit( '[-g] [-S sudo_passwd] [-silent] filename_mp3' ) + snd_ut.silent = silent dbg_out = lambda s, tail='\n': None if silent else dbg.out - data = data_new(filename_mp3) - dbg.out( 'last_sec={}'.format( data.last_sec ) ) + data = snd_ut.data_new(filename_mp3) - snd = snd_new(data, sudo_passwd, dbg_out) + snd = snd_new(data, sudo_passwd) rdr = io_ut.reader_new( sys.stdin, 1, no_buf=True ) diff -ur v11/snddiv_gui.py v12/snddiv_gui.py --- v11/snddiv_gui.py 2020-05-30 17:44:48.000000000 +0900 +++ v12/snddiv_gui.py 2020-09-23 20:59:31.000000000 +0900 @@ -48,12 +48,12 @@ speed_lbs = ('x4', 'x2', 'x1', 'x0.5') shifts = (2, 1, 0, -1) menu_speed = wxo.menu_new( speed_lbs, None, 'x1', shifts ) - get_shift = lambda : shifts[ menu_speed.GetSelection() ] + get_shift = lambda : wxo.menu_get( menu_speed ).v - btn_rw = wxo.wx_new( wx.Button, '<<', min_w=50 ) - btn_ff = wxo.wx_new( wx.Button, '>>', min_w=50 ) + btn_rw = wxo.button_new( '<<', min_w=50 ) + btn_ff = wxo.button_new( '>>', min_w=50 ) - btn_div = wxo.wx_new( wx.Button, '', min_w=50 ) + btn_div = wxo.button_new( '', min_w=50 ) btn_div.Enable(False) area = wxo.label_new( '-/-', min_w=50 ) @@ -76,9 +76,10 @@ s = str( Decimal(s).quantize( Decimal('.01') ) ) wx.CallAfter( pos.SetLabel, s ) - btn_save = wxo.wx_new( wx.Button, 'save', min_w=50 ) + btn_save = wxo.button_new( 'save', min_w=50 ) def save(): + frame = wxo.frame dlg = wx.FileDialog( frame, style=wx.FD_SAVE ) ret = dlg.ShowModal() dlg.Destroy() @@ -157,11 +158,11 @@ wp = wxo.wp lsts = [ - wp( [ wp( btn_rw ), wp( btn_play ), wp( btn_ff ) ] ), + wp( [ wp( btn_rw ), wp( btn_play, prop=1 ), wp( btn_ff ) ], prop=1, flag=wx.EXPAND ), wp( [ wp( cbox_reverse ), wp( menu_speed ) ] ), - wp( [ wp( pos ), wp( btn_div ), wp( area ), wp( btn_save ) ] ), + wp( [ wp( pos ), wp( btn_div ), wp( area ), wp( btn_save, prop=1 ) ], flag=wx.EXPAND ), ] - wxo.wrap( wxo.frame, lsts ) + wxo.wrap_frame( lsts ) wxo.L = empty.new( locals() )