Source code for sox.core

'''Base module for calling SoX '''
from .log import logger

import subprocess
from subprocess import CalledProcessError

from . import NO_SOX

SOXI_ARGS = ['b', 'c', 'a', 'D', 'e', 't', 's', 'r']

ENCODING_VALS = [
    'signed-integer', 'unsigned-integer', 'floating-point', 'a-law', 'u-law',
    'oki-adpcm', 'ima-adpcm', 'ms-adpcm', 'gsm-full-rate'
]


[docs]def sox(args): '''Pass an argument list to SoX. Parameters ---------- args : iterable Argument list for SoX. The first item can, but does not need to, be 'sox'. Returns: -------- status : bool True on success. ''' if args[0].lower() != "sox": args.insert(0, "sox") else: args[0] = "sox" try: logger.info("Executing: %s", ' '.join(args)) process_handle = subprocess.Popen( args, stdout=subprocess.PIPE, stderr=subprocess.PIPE ) out, err = process_handle.communicate() out = out.decode("utf-8") err = err.decode("utf-8") status = process_handle.returncode return status, out, err except OSError as error_msg: logger.error("OSError: SoX failed! %s", error_msg) except TypeError as error_msg: logger.error("TypeError: %s", error_msg) return 1, None, None
[docs]class SoxError(Exception): '''Exception to be raised when SoX exits with non-zero status. ''' def __init__(self, *args, **kwargs): Exception.__init__(self, *args, **kwargs)
def _get_valid_formats(): ''' Calls SoX help for a lists of audio formats available with the current install of SoX. Returns: -------- formats : list List of audio file extensions that SoX can process. ''' if NO_SOX: return [] so = subprocess.check_output(['sox', '-h']) if type(so) is not str: so = str(so, encoding='UTF-8') so = so.split('\n') idx = [i for i in range(len(so)) if 'AUDIO FILE FORMATS:' in so[i]][0] formats = so[idx].split(' ')[3:] return formats VALID_FORMATS = _get_valid_formats()
[docs]def soxi(filepath, argument): ''' Base call to SoXI. Parameters ---------- filepath : str Path to audio file. argument : str Argument to pass to SoXI. Returns ------- shell_output : str Command line output of SoXI ''' if argument not in SOXI_ARGS: raise ValueError("Invalid argument '{}' to SoXI".format(argument)) args = ['sox', '--i'] args.append("-{}".format(argument)) args.append(filepath) try: shell_output = subprocess.check_output( args, stderr=subprocess.PIPE ) except CalledProcessError as cpe: logger.info("SoXI error message: {}".format(cpe.output)) raise SoxiError("SoXI failed with exit code {}".format(cpe.returncode)) shell_output = shell_output.decode("utf-8") return str(shell_output).strip('\n')
[docs]def play(args): '''Pass an argument list to play. Parameters ---------- args : iterable Argument list for play. The first item can, but does not need to, be 'play'. Returns: -------- status : bool True on success. ''' if args[0].lower() != "play": args.insert(0, "play") else: args[0] = "play" try: logger.info("Executing: %s", " ".join(args)) process_handle = subprocess.Popen( args, stdout=subprocess.PIPE, stderr=subprocess.PIPE ) status = process_handle.wait() if process_handle.stderr is not None: logger.info(process_handle.stderr) if status == 0: return True else: logger.info("Play returned with error code %s", status) return False except OSError as error_msg: logger.error("OSError: Play failed! %s", error_msg) except TypeError as error_msg: logger.error("TypeError: %s", error_msg) return False
[docs]class SoxiError(Exception): '''Exception to be raised when SoXI exits with non-zero status. ''' def __init__(self, *args, **kwargs): Exception.__init__(self, *args, **kwargs)
[docs]def is_number(var): '''Check if variable is a numeric value. Parameters ---------- var : object Returns: -------- bool True if var is numeric, False otherwise. ''' try: float(var) return True except ValueError: return False except TypeError: return False
[docs]def all_equal(list_of_things): '''Check if a list contains identical elements. Parameters ---------- list_of_things : list list of objects Returns: -------- bool True if all list elements are the same. ''' return len(set(list_of_things)) <= 1