taped.live_audio_pipelining — taped 0.0.2 documentation

# Source code for taped.live_audio_pipelining

    from functools import partial

    import numpy as np
    from IPython.core.display import clear_output

    from taped.live_audio import launch_audio_tracking
    from taped.util import find_a_default_input_device_index

    from lined.tools import iterize
    from lined import Pipeline

    int16_max = np.iinfo(np.int16).max

    def log_max_chk_to_fv(chk: np.ndarray, gain=50):
        """A chk_to_fv that has to do with volume"""
        return [np.log(max(chk.max(), abs(chk.min()), 1)) / np.log(int16_max) * gain]
        # return np.log(min(1, max(np.abs(chk)))) / np.log(int16_max) * gain

    dflt_chk_to_fv = log_max_chk_to_fv

    def ap_fv_to_viz(fv):
        return f'/><{r"{" * int(sum(fv))}">'

    dflt_fv_to_viz = ap_fv_to_viz

    def ap_chk_to_viz(chk: np.ndarray, gain=50):
        return ap_fv_to_viz(log_max_chk_to_fv(chk, gain))

    dflt_chk_to_viz = ap_chk_to_viz

    class DFLT:
        gain = 10
        cutoff = 50
        dispstr = '*'
        prefix = '|'
        fv_num_sep = '\n'

    def viz_norm(x, gain=10, cutoff=50):
        return min(cutoff, x * gain)

    def ascii_levels(x, viz_norm=viz_norm, dispstr=DFLT.dispstr, prefix=DFLT.prefix):
        return prefix + dispstr * int(viz_norm(x))

    dflt_num_to_viz_str = ascii_levels

    def multipart_fv_str(fv,
                         num_to_viz_str=dflt_num_to_viz_str,
                         fv_num_sep=DFLT.fv_num_sep):
        return fv_num_sep.join(map(num_to_viz_str, fv)) + '\n'

    ascii_levels_fv_to_str = partial(multipart_fv_str,
                                     num_to_viz_str=ascii_levels,
                                     fv_num_sep=DFLT.fv_num_sep)

    raw_fv_to_str = partial(multipart_fv_str,
                            num_to_viz_str=str,
                            fv_num_sep=DFLT.fv_num_sep)

    dflt_fv_to_str = ascii_levels_fv_to_str

    def chk_to_fv_viz(chk: np.ndarray,
                      chk_to_fv=dflt_chk_to_fv,
                      fv_to_str=dflt_fv_to_str):
        """Takes a chk and returns a string representing the fv. Meant to be displayed dynamically"""
        fv = chk_to_fv(chk)
        fv_str = fv_to_str(fv)
        return fv_str

    def refresh_and_print(iterator_output):
        clear_output(wait=True)
        n, viz = iterator_output
        print(n, viz, sep='\n')

    from collections import deque

    class CallableDeque(deque):
        def __call__(self, x):
            self.append(x)

    dflt_output_callback = refresh_and_print

    def make_and_consume_iterator(iterator_func, *iterator_func_args, **iterator_func_kwargs):
        """make an consume and iterator"""
        for _ in iterator_func(*iterator_func_args, **iterator_func_kwargs):
            pass

    def mk_launcher(chk_to_fv=dflt_chk_to_fv,
                    fv_to_viz=dflt_fv_to_viz,
                    input_device_index=None,
                    output_callback=dflt_output_callback):
        if input_device_index is None:
            input_device_index = find_a_default_input_device_index()

        def chk_to_fv_viz(chk):
            return fv_to_viz(chk_to_fv(chk))

        pipe = Pipeline(launch_audio_tracking,
                        iterize(output_callback))

        def launch():
            make_and_consume_iterator(pipe,
                                      chk_callback=chk_to_fv_viz,
                                      input_device_index=input_device_index)

        return launch