You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

100 lines
2.8 KiB
Python

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,
])