Source code for sox.file_info
''' Audio file info computed by soxi.
'''
from .log import logger
import os
from .core import VALID_FORMATS
from .core import soxi
from .core import sox
[docs]def bitrate(input_filepath):
'''
Number of bits per sample (0 if not applicable).
Parameters
----------
input_filepath : str
Path to audio file.
Returns
-------
bitrate : int
number of bits per sample
returns 0 if not applicable
'''
validate_input_file(input_filepath)
output = soxi(input_filepath, 'b')
if output == '0':
logger.warning("Bitrate unavailable for %s", input_filepath)
return int(output)
[docs]def channels(input_filepath):
'''
Show number of channels.
Parameters
----------
input_filepath : str
Path to audio file.
Returns
-------
channels : int
number of channels
'''
validate_input_file(input_filepath)
output = soxi(input_filepath, 'c')
return int(output)
[docs]def duration(input_filepath):
'''
Show duration in seconds (0 if unavailable).
Parameters
----------
input_filepath : str
Path to audio file.
Returns
-------
duration : float
Duration of audio file in seconds.
If unavailable or empty, returns 0.
'''
validate_input_file(input_filepath)
output = soxi(input_filepath, 'D')
if output == '0':
logger.warning("Duration unavailable for %s", input_filepath)
return float(output)
[docs]def encoding(input_filepath):
'''
Show the name of the audio encoding.
Parameters
----------
input_filepath : str
Path to audio file.
Returns
-------
encoding : str
audio encoding type
'''
validate_input_file(input_filepath)
output = soxi(input_filepath, 'e')
return str(output)
[docs]def file_type(input_filepath):
'''
Show detected file-type.
Parameters
----------
input_filepath : str
Path to audio file.
Returns
-------
file_type : str
file format type (ex. 'wav')
'''
validate_input_file(input_filepath)
output = soxi(input_filepath, 't')
return str(output)
[docs]def num_samples(input_filepath):
'''
Show number of samples (0 if unavailable).
Parameters
----------
input_filepath : str
Path to audio file.
Returns
-------
n_samples : int
total number of samples in audio file.
Returns 0 if empty or unavailable
'''
validate_input_file(input_filepath)
output = soxi(input_filepath, 's')
if output == '0':
logger.warning("Number of samples unavailable for %s", input_filepath)
return int(output)
[docs]def sample_rate(input_filepath):
'''
Show sample-rate.
Parameters
----------
input_filepath : str
Path to audio file.
Returns
-------
samplerate : float
number of samples/second
'''
validate_input_file(input_filepath)
output = soxi(input_filepath, 'r')
return float(output)
[docs]def silent(input_filepath, threshold=0.001):
'''
Determine if an input file is silent.
Parameters
----------
input_filepath : str
The input filepath.
threshold : float
Threshold for determining silence
Returns
-------
is_silent : bool
True if file is determined silent.
'''
validate_input_file(input_filepath)
stat_dictionary = stat(input_filepath)
mean_norm = stat_dictionary['Mean norm']
if mean_norm is not float('nan'):
if mean_norm >= threshold:
return False
else:
return True
else:
return True
[docs]def validate_output_file(output_filepath):
'''Output file validation function. Checks that file can be written, and
has a valid file extension. Throws a warning if the path already exists,
as it will be overwritten on build.
Parameters
----------
output_filepath : str
The output filepath.
Returns:
--------
output_filepath : str
The output filepath.
'''
nowrite_conditions = [
bool(os.path.dirname(output_filepath)) or\
not os.access(os.getcwd(), os.W_OK),
not os.access(os.path.dirname(output_filepath), os.W_OK)]
if all(nowrite_conditions):
raise IOError(
"SoX cannot write to output_filepath {}".format(output_filepath)
)
ext = file_extension(output_filepath)
if ext not in VALID_FORMATS:
logger.info("Valid formats: %s", " ".join(VALID_FORMATS))
logger.warning(
"This install of SoX cannot process .{} files.".format(ext)
)
if os.path.exists(output_filepath):
logger.warning(
'output_file: %s already exists and will be overwritten on build',
output_filepath
)
[docs]def file_extension(filepath):
'''Get the extension of a filepath.
Parameters
----------
filepath : str
File path.
Returns:
--------
extension : str
The file's extension
'''
return os.path.splitext(filepath)[1][1:]
[docs]def info(filepath):
'''Get a dictionary of file information
Parameters
----------
filepath : str
File path.
Returns:
--------
info_dictionary : dict
Dictionary of file information. Fields are:
* channels
* sample_rate
* bitrate
* duration
* num_samples
* encoding
* silent
'''
info_dictionary = {
'channels': channels(filepath),
'sample_rate': sample_rate(filepath),
'bitrate': bitrate(filepath),
'duration': duration(filepath),
'num_samples': num_samples(filepath),
'encoding': encoding(filepath),
'silent': silent(filepath)
}
return info_dictionary
[docs]def stat(filepath):
'''Returns a dictionary of audio statistics.
Parameters
----------
filepath : str
File path.
Returns
-------
stat_dictionary : dict
Dictionary of audio statistics.
'''
stat_output = _stat_call(filepath)
stat_dictionary = _parse_stat(stat_output)
return stat_dictionary
def _stat_call(filepath):
'''Call sox's stat function.
Parameters
----------
filepath : str
File path.
Returns
-------
stat_output : str
Sox output from stderr.
'''
validate_input_file(filepath)
args = ['sox', filepath, '-n', 'stat']
_, _, stat_output = sox(args)
return stat_output
def _parse_stat(stat_output):
'''Parse the string output from sox's stat function
Parameters
----------
stat_output : str
Sox output from stderr.
Returns
-------
stat_dictionary : dict
Dictionary of audio statistics.
'''
lines = stat_output.split('\n')
stat_dict = {}
for line in lines:
split_line = line.split(':')
if len(split_line) == 2:
key = split_line[0]
val = split_line[1].strip(' ')
try:
val = float(val)
except ValueError:
val = None
stat_dict[key] = val
return stat_dict