sf1000/averagesong.py

78 lines
2.1 KiB
Python

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()