import itertools import pathlib import typing import numpy import scipy.io.wavfile from matplotlib import pyplot # pylint: disable=unused-import; frequently used in shell def numpy_array_from_file( path: typing.Union[str, pathlib.Path], dtype ) -> numpy.ndarray: if isinstance(path, str): path = pathlib.Path(path) return numpy.frombuffer(path.read_bytes(), dtype=dtype) def split_sequence_by_delimiter( sequence: typing.Sequence, delimiter: typing.Any, delimiter_min_length: int = 1 ) -> typing.Iterator[typing.Sequence]: slice_start_index, slice_length = 0, 0 for is_delimiter, group in itertools.groupby( sequence, key=lambda item: item == delimiter ): group_length = sum(1 for _ in group) if is_delimiter and group_length >= delimiter_min_length: if slice_length > 0: yield sequence[slice_start_index : slice_start_index + slice_length] slice_start_index += slice_length + group_length slice_length = 0 else: slice_length += group_length if slice_length > 0: yield sequence[slice_start_index : slice_start_index + slice_length] def trim_where( # https://docs.python.org/3.8/library/collections.abc.html#collections-abstract-base-classes sequence: typing.Sequence, condition: typing.Sequence[bool], ) -> typing.Sequence: start = 0 for item_condition in condition: if item_condition: start += 1 else: break stop = len(sequence) assert stop == len(condition) for item_condition in condition[::-1]: if item_condition: stop -= 1 else: break return sequence[start:stop] def wavfile_read_mono( path: typing.Union[pathlib.Path, str] ) -> typing.Tuple[int, numpy.ndarray]: # https://docs.scipy.org/doc/scipy/reference/generated/scipy.io.wavfile.read.html rate, data = scipy.io.wavfile.read(path) if len(data.shape) == 1: return rate, data data_first_channel = data[:, 0] for channel_index in range(1, data.shape[1]): assert (data_first_channel == data[:, channel_index]).all() return rate, data_first_channel