import scipy.io.wavfile import scipy.signal import numpy import argparse import logging LOG_LEVELS = [logging.WARNING, logging.INFO, logging.DEBUG] LOGGER=logging.getLogger(__name__) def parse_args(*args): """ get the CLI args """ parser = argparse.ArgumentParser(prog="granule", description="Extract granules from a wav file") parser.add_argument('input', nargs='*', help="Input filename") parser.add_argument('-p', '--playlist', help="Input playlist") parser.add_argument('-o', '--output', help="Output filename") parser.add_argument("-v", "--verbosity", action="count", help="increase output verbosity", default=0) return parser.parse_args(*args) def normalize(buffer): amplitude = max(numpy.max(buffer), -numpy.min(buffer)) return buffer/amplitude; def accumulate(filename, buffer): """ Accumulates a song into the accumulation buffer """ LOGGER.info("Reading %s", filename) rate, data = scipy.io.wavfile.read(filename) if len(data.shape) > 1: data = numpy.mean(data, axis=1) data = normalize(data) if rate != 44100: data = scipy.signal.resample(data, len(data)*44100 // rate) if buffer is None: return data out_len = max(len(buffer), len(data)) if len(buffer) < out_len: buffer.resize(out_len, refcheck=False) if len(data) < out_len: data.resize(out_len, refcheck=False) buffer += data return buffer def main(): args = parse_args() logging.basicConfig(level=LOG_LEVELS[min( args.verbosity, len(LOG_LEVELS) - 1)]) if args.playlist: with open(args.playlist) as file: for line in file: args.input.append(line.strip()) output = None total = len(args.input) for num, infile in enumerate(args.input): output = accumulate(infile, output) output = normalize(output) LOGGER.info("Output file: %d samples (%.2f seconds)", len(output), len(output)/44100) if (args.output): scipy.io.wavfile.write(args.output, 44100, output) if __name__ == "__main__": main()