cog/Frameworks/libsidplay/sidplay-residfp-code/fc-curves/scripts/split-by-silence.py

121 lines
3.6 KiB
Python
Executable File

#!/usr/bin/python
import struct, sys, wave
class UnsupportedWaveformat(Exception):
pass
class InvalidArgs(Exception):
pass
class AnalysisError(Exception):
pass
def split_wave(input, pattern, multiplier=8):
wv = wave.open(input, 'r')
if wv.getnchannels() != 1:
raise UnsupportedWaveformat, "mono audio only"
if wv.getsampwidth() != 2:
raise UnsupportedWaveformat, "16-bit pcm only"
readlen = 128
outhandle = None
seqnum = -1
frames = None
sum = 0
# highpass filter
levelcomp_coeff = (50 * 2 * 3.14159) / wv.getframerate()
levelcomp = 0
pos = 0
while True:
# read in chunks, classify as silence or as signal
datachar = wv.readframes(readlen)
pos += readlen
if frames is not None:
frames += readlen
# wave finish?
if len(datachar) < readlen * 2:
if outhandle is not None:
outhandle.writeframes(datachar)
outhandle.close();
cliplen = float(frames) / outhandle.getframerate()
print "End writing wave %d, %.1f s clip" % (seqnum, cliplen)
outhandle = None
break
# get wave values
datatuple = struct.unpack("%sh" % readlen, datachar)
# analyse signal levels.
_sum = 0
_min = 0
_max = 0
for _ in datatuple:
_ /= 32768.
if _ < _min:
_min = _
if _ > _max:
_max = _
levelcomp = _ * levelcomp_coeff + (1 - levelcomp_coeff) * levelcomp
_sum += (_ - levelcomp) ** 2
_sum /= readlen
sum = (sum * 15 + _sum) / 16;
start = _max > 0.2# or sum > 5e-7
end = _min < -0.2# or sum < 1e-7
# trigger silence
if end:
if outhandle is not None:
outhandle.close()
cliplen = float(frames) / outhandle.getframerate()
print "End writing wave %d, %.1f seconds" % (seqnum, cliplen)
if cliplen < 4:
raise AnalysisError, "sound prematurely clipped at %f" % (pos/outhandle.getframerate())
if cliplen > 6:
raise AnalysisError, "sound clipped too late at %f" % (pos/outhandle.getframerate())
outhandle = None
frames = 0
# trigger signal
if start:
if outhandle is None:
seqnum += 1
outhandle = wave.open(pattern % (multiplier * seqnum), "w")
outhandle.setnchannels(1)
outhandle.setframerate(wv.getframerate())
outhandle.setsampwidth(2);
if frames is not None:
cliplen = float(frames) / outhandle.getframerate()
print "Begun writing wave %d after %.1f s silence" % (seqnum, cliplen)
if cliplen < 0.05:
raise AnalysisError, "silence too short";
if cliplen > 1.5:
raise AnalysisError, "silence too long";
frames = 0
continue
# write if we got handle
if outhandle is not None:
outhandle.writeframes(datachar)
if seqnum != 2048 / multiplier - 1:
raise AnalysisError, "Wrong count of waves written. Results are probably invalid."
def main(args):
if len(args) != 2:
raise InvalidArgs, "Usage: program <inputfile> { lp | hp }"
return split_wave(args[0], args[1] + "_%04d.wav")
return 0
if __name__ == '__main__':
main(sys.argv[1:])