Source code for sox.core
'''Base module for calling SoX '''
import logging
import subprocess
from subprocess import CalledProcessError
from . import NO_SOX
SOXI_ARGS = ['b', 'c', 'a', 'D', 'e', 't', 's', 'r']
[docs]def enquote_filepath(fpath):
"""Wrap a filepath in double-quotes to protect difficult characters.
"""
if ' ' in fpath:
fpath = '"{}"'.format(fpath.strip("'").strip('"'))
return fpath
[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:
logging.info("Executing: %s", " ".join(args))
process_handle = subprocess.Popen(
args, stdout=subprocess.PIPE, stderr=subprocess.PIPE
)
out, err = process_handle.communicate()
status = process_handle.returncode
if out is not None:
logging.info(out)
if status == 0:
return True
else:
logging.info("SoX returned with error code %s", status)
logging.info(out)
logging.info(err)
return False
except OSError as error_msg:
logging.error("OSError: SoX failed! %s", error_msg)
except TypeError as error_msg:
logging.error("TypeError: %s", error_msg)
return False
[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 []
shell_output = subprocess.check_output(
"sox -h | grep 'AUDIO FILE FORMATS'",
shell=True
)
formats = str(shell_output).strip('\n').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 = ['soxi']
args.append("-{}".format(argument))
args.append(enquote_filepath(filepath))
try:
shell_output = subprocess.check_output(
" ".join(args),
shell=True, stderr=subprocess.PIPE
)
except CalledProcessError as cpe:
logging.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:
logging.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:
logging.info(process_handle.stderr)
if status == 0:
return True
else:
logging.info("Play returned with error code %s", status)
return False
except OSError as error_msg:
logging.error("OSError: Play failed! %s", error_msg)
except TypeError as error_msg:
logging.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