Public functions
get_minval
Return the min value for a given sampwidth.
Parameters
- size: (int) the sampwidth
- signed: (bool) if the values will be signed or not
Raises
- SampleWidthError: Invalid given size.
Returns
View Source
@staticmethod
def get_minval(size, signed=True):
"""Return the min value for a given sampwidth.
:param size: (int) the sampwidth
:param signed: (bool) if the values will be signed or not
:raise: SampleWidthError: Invalid given size.
:return: (int) the min value
"""
if not signed:
return 0
elif size == 1:
return -128
elif size == 2:
return -32768
elif size == 4:
return -2147483648
raise SampleWidthError(size)
get_maxval
Return the max value for a given sampwidth.
Parameters
- size: (int) the sampwidth
- signed: (bool) if the values will be signed or not
Raises
- SampleWidthError: Invalid given size.
Returns
View Source
@staticmethod
def get_maxval(size, signed=True):
"""Return the max value for a given sampwidth.
:param size: (int) the sampwidth
:param signed: (bool) if the values will be signed or not
:raise: SampleWidthError: Invalid given size.
:return: (int) the max value
"""
if signed and size == 1:
return 127
elif size == 1:
return 255
elif signed and size == 2:
return 32767
elif size == 2:
return 65535
elif signed and size == 4:
return 2147483647
elif size == 4:
return 4294967295
raise SampleWidthError(size)
get_nchannels
Return the number of channels in the frames.
View Source
def get_nchannels(self):
"""Return the number of channels in the frames."""
return self._nchannels
get_sampwidth
Return the size of the frames in (1, 2, 4).
View Source
def get_sampwidth(self):
"""Return the size of the frames in (1, 2, 4)."""
return self._sampwidth
get_sample
Return the value of given sample index.
Parameters
- i: (int) index of the sample to get value
Returns
View Source
def get_sample(self, i):
"""Return the value of given sample index.
:param i: (int) index of the sample to get value
:return: (int) value
"""
start = i * self._sampwidth
return self.__frame_to_sample(self._frames[start:start + self._sampwidth])
minmax
Return the minimum and maximum values of all samples in the frames.
Returns
- (int, int) Min and max amplitude values, or (0,0) if empty frames.
View Source
def minmax(self):
"""Return the minimum and maximum values of all samples in the frames.
:return: (int, int) Min and max amplitude values, or (0,0) if empty frames.
"""
if len(self._frames) > 0:
val_min = self.get_maxval(self._sampwidth)
val_max = self.get_minval(self._sampwidth)
for i in range(len(self._frames) // self._sampwidth):
val = self.get_sample(i)
if val > val_max:
val_max = val
if val < val_min:
val_min = val
return (val_min, val_max)
return (0, 0)
min
Return the minimum of the values of all samples in the frames.
View Source
def min(self):
"""Return the minimum of the values of all samples in the frames."""
return self.minmax()[0]
max
Return the maximum of the values of all samples in the frames.
View Source
def max(self):
"""Return the maximum of the values of all samples in the frames."""
return self.minmax()[1]
absmax
Return the maximum of the *absolute value of all samples in the frames.*
View Source
def absmax(self):
"""Return the maximum of the *absolute value* of all samples in the frames."""
val_min, val_max = self.minmax()
return max(abs(val_min), abs(val_max))
avg
Return the average over all samples in the frames.
Returns
- (float) Average value rounded to 2 digits.
View Source
def avg(self):
"""Return the average over all samples in the frames.
:return: (float) Average value rounded to 2 digits.
"""
if len(self._frames) == 0:
return 0
samples_sum = 0.0
nb_samples = len(self._frames) / self._sampwidth
for i in range(int(nb_samples)):
samples_sum += self.get_sample(i)
return round(samples_sum / nb_samples, 2)
rms
Return the root-mean-square of the frames.
Returns
- (float) sqrt(sum(S_i^2) / n) rounded to 2 digits
View Source
def rms(self):
"""Return the root-mean-square of the frames.
:return: (float) sqrt(sum(S_i^2) / n) rounded to 2 digits
"""
if len(self._frames) == 0:
return 0.0
square_sum = 0.0
nb_samples = len(self._frames) / self._sampwidth
for i in range(int(nb_samples)):
val = self.get_sample(i)
square_sum += val * val
return round(math.sqrt(square_sum / nb_samples), 2)
cross
Return the number of zero crossings in frames.
Returns
- (int) Number of zero crossing or -1 if empty frames
View Source
def cross(self):
"""Return the number of zero crossings in frames.
:return: (int) Number of zero crossing or -1 if empty frames
"""
n_cross = -1
prev_val = 17
for i in range(len(self._frames) // self._sampwidth):
val = self.get_sample(i) < 0
if val != prev_val:
n_cross += 1
prev_val = val
return n_cross
clip
Return the number of frames with a value higher than the one of the factor.
Parameters
- factor: (float) All frames outside the interval are clipped.
Returns
View Source
def clip(self, factor=0.5):
"""Return the number of frames with a value higher than the one of the factor.
:param factor: (float) All frames outside the interval are clipped.
:return: (int)
"""
max_val = int(AudioFrames.get_maxval(self._sampwidth) * float(factor))
min_val = int(AudioFrames.get_minval(self._sampwidth) * float(factor))
n_clip = 0
for i in range(len(self._frames) // self._sampwidth):
val = self.get_sample(i)
if val >= max_val or val <= min_val:
n_clip += 1
return n_clip
clipping_rate
Return the clipping rate of the frames.
Percentage of samples with a value higher than the one corresponding
to the factor. Factor has to be between 0 and 1.
Parameters
- factor: (float) All frames outside the interval are clipped.
Returns
- (float) clipping rate value. To be multiplied by 100 to get the percentage!
View Source
def clipping_rate(self, factor=0.5):
"""Return the clipping rate of the frames.
Percentage of samples with a value higher than the one corresponding
to the factor. Factor has to be between 0 and 1.
:param factor: (float) All frames outside the interval are clipped.
:return: (float) clipping rate value. To be multiplied by 100 to get the percentage!
"""
if len(self._frames) == 0:
return 0.0
return float(self.clip(factor)) / (len(self._frames) // self._sampwidth)
get_frames
Return the stored frames.
View Source
def get_frames(self):
"""Return the stored frames."""
return self._frames
byteswap
Converts big-endian samples to little-endian and vice versa.
View Source
def byteswap(self):
"""Converts big-endian samples to little-endian and vice versa."""
try:
import audioop
audioop.byteswap(self._frames, self._sampwidth)
except ModuleNotFoundError:
raise NotImplementedError
findfactor
Return a factor F such that rms(add(mul(reference, -F))) is minimal.
Estimates the factor with which you should multiply reference to make
it match as well as possible to the frames.
Parameters
View Source
def findfactor(self, reference):
"""Return a factor F such that rms(add(mul(reference, -F))) is minimal.
Estimates the factor with which you should multiply reference to make
it match as well as possible to the frames.
"""
try:
import audioop
audioop.findfactor(self._frames, reference)
except ModuleNotFoundError:
raise NotImplementedError
reverse
Reverse the samples in the frames.
View Source
def reverse(self):
"""Reverse the samples in the frames."""
try:
import audioop
audioop.reverse(self._frames, self._sampwidth)
except ModuleNotFoundError:
raise NotImplementedError
mul
Return frames for which all samples are multiplied by factor.
All samples in the original frames are multiplied by the floating-point
value factor. Samples are truncated in case of overflow.
Parameters
- factor: (float) the factor which will be applied to each sample.
Returns
View Source
def mul(self, factor):
"""Return frames for which all samples are multiplied by factor.
All samples in the original frames are multiplied by the floating-point
value factor. Samples are truncated in case of overflow.
:param factor: (float) the factor which will be applied to each sample.
:return: (bytes) converted frames
"""
if len(self._frames) == 0:
return b''
factor = float(factor)
val_min = self.get_minval(self._sampwidth)
val_max = self.get_maxval(self._sampwidth)
mul_frames = self.__zero_frames()
for i in range(len(self._frames) // self._sampwidth):
val = float(self.get_sample(i))
mul_val = max(val_min, min(val_max, int(val * factor)))
mul_frames[i] = self.__sample_to_frame(mul_val)
return b''.join(mul_frames)
bias
Return frames that is the original ones with a bias added to each sample.
All samples in the original frames are summed with the given value.
Samples are truncated in case of overflow.
Parameters
- value: (int) the bias which will be applied to each sample.
Returns
View Source
def bias(self, value):
"""Return frames that is the original ones with a bias added to each sample.
All samples in the original frames are summed with the given value.
Samples are truncated in case of overflow.
:param value: (int) the bias which will be applied to each sample.
:return: (bytes) converted frames
"""
if len(self._frames) == 0:
return b''
value = int(value)
val_min = self.get_minval(self._sampwidth)
val_max = self.get_maxval(self._sampwidth)
mul_frames = self.__zero_frames()
for i in range(len(self._frames) // self._sampwidth):
val = self.get_sample(i)
mul_val = max(val_min, min(val_max, val + value))
mul_frames[i] = self.__sample_to_frame(mul_val)
return b''.join(mul_frames)
change_sampwidth
Return frames with the given number of bytes.
Parameters
- size: (int) new sample width of the frames. (1 for 8 bits, 2 for 16 bits, 4 for 32 bits)
Returns
View Source
def change_sampwidth(self, size):
"""Return frames with the given number of bytes.
:param size: (int) new sample width of the frames.
(1 for 8 bits, 2 for 16 bits, 4 for 32 bits)
:return: (bytes) converted frames
"""
if size not in (1, 2, 4):
raise SampleWidthError(size)
zero_byte = b'\x00' * size
size_frames = [zero_byte] * (len(self._frames) // self._sampwidth)
for i in range(len(self._frames) // self._sampwidth):
val = self.get_sample(i)
val = val << (4 - self._sampwidth) * 8
if size == 2:
size_frames[i] = struct.pack('<h', val >> 16)
elif size == 4:
size_frames[i] = struct.pack('<l', val)
elif size == 1:
size_frames[i] = struct.pack('<b', val >> 24)
return b''.join(size_frames)
resample
Return re-sampled frames with the given new framerate.
Parameters
- in_rate: (int) The original sample rate of the audio frames
- out_rate: (int) The desired sample rate to resample the audio frames to
Returns
- (bytes) the resampled audio frames.
Raises
- FrameRateError: invalid given in_rate
- FrameRateError: invalid given out_rate
- NotImplementedError: can't resample from inrate to outrate
View Source
def resample(self, in_rate, out_rate=16000):
"""Return re-sampled frames with the given new framerate.
:param in_rate: (int) The original sample rate of the audio frames
:param out_rate: (int) The desired sample rate to resample the audio frames to
:return: (bytes) the resampled audio frames.
:raise: FrameRateError: invalid given in_rate
:raise: FrameRateError: invalid given out_rate
:raise: NotImplementedError: can't resample from in_rate to out_rate
"""
if len(self._frames) == 0:
return b''
in_rate = int(in_rate)
out_rate = int(out_rate)
if in_rate < 8000:
raise FrameRateError(in_rate)
if out_rate < 8000:
raise FrameRateError(out_rate)
try:
frames = self._re_sample(in_rate, out_rate)
return frames
except NotImplementedError as e:
logging.warning("Deprecated. Since 'audioop' will be removed of the Python standard library, re-sampling will not be fully available from Python 3.13. Any help is welcome to implement a self-implemented solution.")
try:
import audioop
return audioop.ratecv(self._frames, self._sampwidth, self._nchannels, in_rate, out_rate, None)[0]
except ModuleNotFoundError:
raise e