import logging import shlex import wave from subprocess import PIPE, Popen import numpy as np ENCODINGS_MAPPING = { np.int16: 's16', np.float32: 'f32', np.float64: 'f64', } PIPE_CHAR = '-' logger = logging.getLogger('pysndfx') class SoxInput(object): pipe = '-' def __init__(self): self.cmd_prefix = None class FilePathInput(SoxInput): def __init__(self, filepath): super(FilePathInput, self).__init__() info_cmd = 'sox --i -c ' + filepath logger.debug("Running info command : %s" % info_cmd) stdout, stderr = Popen(shlex.split(info_cmd, posix=False), stdout=PIPE, stderr=PIPE).communicate() self.channels = int(stdout) self.cmd_prefix = filepath class FileBufferInput(SoxInput): def __init__(self, fp): super(FileBufferInput, self).__init__() wave_file = wave.open(fp, mode='rb') # wave.open() seems to support only 16bit encodings self.channels = wave_file.getnchannels() self.data = np.frombuffer(wave_file.readframes(wave_file.getnframes()), dtype=np.int16) self.cmd_prefix = ' '.join([ '-t s16', # int16 encoding by default '-r ' + str(wave_file.getframerate()), '-c ' + str(self.channels), PIPE_CHAR, ]) class NumpyArrayInput(SoxInput): def __init__(self, snd_array, rate): super(NumpyArrayInput, self).__init__() self.channels = snd_array.ndim self.cmd_prefix = ' '.join([ '-t ' + ENCODINGS_MAPPING[snd_array.dtype.type], '-r ' + str(rate), '-c ' + str(self.channels), PIPE_CHAR, ]) class SoxOutput(object): def __init__(self): self.cmd_suffix = None class FilePathOutput(SoxOutput): def __init__(self, filepath, samplerate, channels): super(FilePathOutput, self).__init__() self.cmd_suffix = ' '.join(['-r ' + str(samplerate), '-c ' + str(channels), filepath]) class FileBufferOutput(SoxOutput): def __init__(self, fp, samplerate, channels): super(FileBufferOutput, self).__init__() self.writer = wave.open(fp, mode='wb') self.writer.setnchannels(channels) self.writer.setframerate(samplerate) self.writer.setsampwidth(2) self.cmd_suffix = ' '.join([ '-t ' + ENCODINGS_MAPPING[np.int16], '-r ' + str(samplerate), '-c ' + str(channels), PIPE_CHAR, ]) def write(self, data): self.writer.writeframesraw(data) class NumpyArrayOutput(SoxOutput): def __init__(self, encoding, samplerate, channels): super(NumpyArrayOutput, self).__init__() self.cmd_suffix = ' '.join([ '-t ' + ENCODINGS_MAPPING[encoding], '-r ' + str(samplerate), '-c ' + str(channels), PIPE_CHAR, ])