Example #1
0
 def list_children(self):
     """
     cat: info
     """
     info_block("Children in '{0}':".format(self.name))
     children = ["{0} ({1})".format(i.name, i.reltype) for i in self.children]
     info_list(children)
Example #2
0
def sd_select_device(device_type='in'):
    """
    type: in or out
    returns [index, name] of device
    """
    info_title("Devices by index ({0} found):".format(len(sd.query_devices())))
    for i in str(sd.query_devices()).split('\n'):
        info_line(i)
    while True:
        p("Enter desired device index")
        device_ind = inpt('int')
        try:
            device = sd.query_devices()[device_ind]
        except IndexError:
            err_mess("No device with index {0}".format(device_ind))
            continue
        if device_type in ('in', 'input'):
            if device['max_input_channels'] < 1:
                err_mess("Device cannot be used as an input")
                continue
        elif device_type in ('out', 'output'):
            if device['max_output_channels'] < 1:
                err_mess("Device cannot be used as an output")
        device_name = device['name']
        info_block("'{0}' selected".format(device_name))
        return [device_ind, device_name]
Example #3
0
    def save_metadata(self):
        """
        define parse_write_meta(dict: attrs) to define which attrs to write
        """
        info_block("saving {0} '{1}' metadata...".format(
            self.reltype, self.name))

        # must copy list, otherwise we will edit this object's __dict__
        attrs = {k: v for k, v in vars(self).items()}
        attrs = self.parse_write_meta(attrs)
        try:
            del attrs["_rel_data"]
        except KeyError:
            pass
        attrs["__module__"] = self.__class__.__module__
        attrs["__class__"] = self.__class__.__name__

        from src.project_loader import RelTypeEncoder
        attrs = RelTypeEncoder.parse_container_obj_sets(
            attrs, self.get_data_dir())

        fullpath = self.get_datafile_fullpath()

        with open(fullpath, 'w') as f:
            json.dump(attrs, fp=f, cls=RelTypeEncoder, indent=2)
Example #4
0
    def view_waveform(self, start=0, end=None, precision=50):
        """
        cat: info
        desc: show the waveform of this audio
        args:
            [start: seconds/beats to begin view window. default beginning]
            [end: seconds/beats to end view window. -1 selects end. default end]
            [precision: percent of how detailed the plot should be. default 50]
        """
        start = inpt_validate(start, 'beatsec')
        if (end is None) or (end == "-1"):
            end = self.size_samps()
        else:
            end = inpt_validate(end, 'beatsec')
            if end.samples_value >= self.size_samps():
                end = self.size_samps()
        if end <= start:
            err_mess("End cannot be before or equal to start")
            return
        precision = inpt_validate(precision, 'pcnt', allowed=[5, 10000])

        info_block("Generating waveform at {0}%...".format(precision))

        anlsys = Analysis(self, start=start, end=end)
        frame_len = (end - start) / (precision * 2)
        anlsys.set_frame_lengths(frame_len)

        left = anlsys.arr[:, 0]
        right = anlsys.arr[:, 1]

        anlsys.plot(left, right, fill=True)
Example #5
0
def process_validate(command, obj):
    """
    check command as valid or one of the shortcuts
    return True on valid
    """
    if command == []:
        err_mess("No command entered")
        command = "None"
    elif command == ['']:
        err_mess(
            "Only alphanumeric characters, spaces, and underscores are allowed"
        )
    elif command[0] in ("q", "quit"):
        p("Save before exiting?")
        if inpt("yn"):
            obj.save()
        info_block("Exiting processing of {0} '{1}'...".format(
            obj.reltype, obj.name))
        raise Cancel(obj)
    elif command[0] in ("o", "options"):
        obj.options()
    elif command[0] in ("h", "help"):
        pass  # callback handled during inpt()
    else:
        return True
    return False
Example #6
0
 def record_live(self):
     """
     record -- but get this -- live!
     """
     section_head("Record mode")
     device_ind, device_name = sd_select_device()
     p("Enter recording duration (in seconds)")
     record_time = inpt('beatsec')
     p('Choose sample rate to record at, in samples per second. Hit enter to use default 44100')
     rate = inpt('int', required=False)
     if rate == '':
         rate = 44100
     self.rate = Units.rate(rate)
     print("  Press Enter to begin recording, or 'q' to quit: ", end="")
     inpt("none", required=False)
     time.sleep(0.05)
     section_head("Recording at input {0} ({1}) for {2}".format(device_ind, \
         device_name, record_time))
     sd.default.channels = 2
     recording = sd.rec(
         ind(record_time * self.rate), 
         self.rate.magnitude, 
         device=device_name)
     sd.wait()
     info_block("Finished recording")
     self.arr = recording
     if len(self.arr.shape) < 2:
         transpose = self.arr.reshape(-1, 1)
         self.arr = np.hstack((transpose, transpose))
     self.source_block = {
         'live recording': "input '{0}'".format(device_name)
     }
Example #7
0
 def rhythms_help(self):
     info_block(
         "Rhythms are made up of multiple beats. Each beat follows the format of " + \
         "<place> <length> <optional: start>, all of which are in beat notation: ",
         trailing_newline=False
     )
     info_block(
         "<place>: the time at which this beat starts within the rhythm. For example" +\
         " 'qn' would mean this beat starts one quarter-note after the beginning of the rhythm",
         trailing_newline=False
     )
     info_block(
         "<length>: how long the snippet of the sample will be. 'qn' would mean it lasts for one quarter-note. " +\
         "no entry, or 0, means that the entire sample will be used",
         trailing_newline=False
     )
     info_block(
         "<start>: an optional parameter, which selects where in the sample to start playback " +\
         "for this one beat, as if trimming it on the front. 'qn' means the beat would begin " +\
         "from one quarter-note in to the sample",
         trailing_newline=False
     )
     print("        3q 1q")
     info_block(
         "will create a beat that start on the third quarter of the rhythm, and" + \
         "lasts for one quarter note"
     )
     p("Do you need info on how to create properly formed beats?", o="y/n")
     if inpt('yn'):
         beat_options()
Example #8
0
    def find_peaks(self, frames):
        """
        returns peaks as (sample index, slope)
        """
        info_block("Finding peaks...")

        # find highest positive slopes between frames
        slopes = []
        frm_ind = 0
        while frm_ind < len(frames): # (index, avg amp)
            highest_slope = 0
            compare_ind = frm_ind + 1
            # get highest slope from this frame, with no dips in between
            while ( # while frame is highest than last and not past end
                    compare_ind < len(frames) ) and (
                    frames[compare_ind][1] > frames[compare_ind - 1][1]
                ):
                # 1000 is arbitrary, just to make the numbers nicer
                new_slope = 1000 * (frames[compare_ind][1] - frames[frm_ind][1]) / (compare_ind - frm_ind)
                highest_slope = new_slope if new_slope > highest_slope else highest_slope
                compare_ind += 1
            if highest_slope != 0:
                slopes.append((frames[frm_ind][0], highest_slope))
            frm_ind += 1

        return np.asarray(slopes)
Example #9
0
    def filter_peaks(self, peaks):
        """
        returns peaks as (sample_index, slope)
        """
        info_block("Filtering peaks...")

        avg_slope = np.mean(peaks[:,1])
        peaks = peaks[peaks[:,1] >= avg_slope]

        sorted_peaks = NpOps.sort(peaks, 1)

        p_ind = 0
        while p_ind < sorted_peaks.shape[0]:
            comp_ind = p_ind + 1
            while comp_ind < sorted_peaks.shape[0]:
                comp_val = sorted_peaks[comp_ind][0]
                # remove smaller items. 4 seems to get them all
                if (comp_val - (5 * self.frame_length) <
                    sorted_peaks[p_ind][0] <
                    comp_val + (5 * self.frame_length)
                ):
                    sorted_peaks = np.delete(sorted_peaks, comp_ind, 0)
                else:
                    comp_ind += 1
            p_ind += 1

        return sorted_peaks # (sample_index, slope)
Example #10
0
 def save_globals():
     """
     dct: dict of vars to save
     """
     info_block("Saving global data...")
     dct = {i:getattr(_RelGlobalsContainer, i) for i in _RelGlobalsContainer._write_vars}
     with open(RelGlobals.data_file(), "w") as f:
         json.dump(dct, f, indent=2)
Example #11
0
 def info(self):
     """
     cat: info
     """
     info_block("{0} '{1}'".format(self.reltype, self.name))
     info_line("Stored at '{0}'".format(self.path))
     info_line("Samplerate: {0}".format(self.rate))
     self.list_children()
Example #12
0
 def list_beats(self):
     sorted_beats = selection_sort(self.beats,
                                   ind=0,
                                   func_on_val=secs,
                                   func_args=[60, 'val'],
                                   low_to_high=True)
     for i in sorted_beats:
         info_block("- " + self.beat_repr(i), newlines=False)
Example #13
0
 def save_settings():
     """
     save settings to settingsfile
     """
     info_block("Saving settings...")
     attrs = [attr for attr in dir(_SettingsContainer) if "__" not in attr and attr != "_defaults"]
     dct = {i:getattr(_SettingsContainer, i) for i in attrs}
     with open(RelGlobals.settings_file(), "w") as f:
         json.dump(dct, f, indent=2)
Example #14
0
 def mute(self):
     """
     cat: edit
     desc: mute an active pair
     """
     info_block("Choose an active pair to mute")
     act = self.choose('active')
     if act is not None:
         act.muted = True
Example #15
0
 def process_message(self):
     """
     this is only called when the prop is not a controller
     """
     try:
         val = self.get_val()
     except AttributeError:
         info_block("{0} '{1}' has no value assigned yet. Use the 'set' process".format(self.reltype, self.name), indent=2)
     else:
         info_block("{0} '{1}' has a value of {2}".format(self.reltype, self.name, val), indent=2)
Example #16
0
    def rename(self, name=None):
        """
        cat: meta
        dev: call this method via super, and implement renaming of files other than 
        datafile and its self.path directory
        """
        old_name = self.name
        if old_name is not None:
            old_data_dir = self.get_data_dir()
            old_datafile_name = self.get_data_filename()

        if name is None:
            p("Give this {0} a name".format(self.reltype))
            name = inpt("obj")
        else:
            name = inpt_validate(name, 'obj')

        # validate
        if hasattr(self.parent, "validate_child_name"):
            if self.parent.validate_child_name(self, name):
                self.name = name
                info_block("Named '{0}'".format(name))
            else:
                err_mess("Invalid name")
                self.rename()
        else:
            if Settings.is_debug():
                show_error(
                    AttributeError(
                        "Parent obj '{0}' does not have validate_child_name".
                        format(self.parent)))
            else:
                try:
                    log_err(
                        "Parent object type {0} has no 'validate_child_name' method"
                        .format(self.parent.reltype))
                except AttributeError:
                    log_err(
                        "Parent object '{0}' of '{1}' has no 'validate_child_name' method"
                        .format(self.parent, self))
            self.name = name
            info_block("Named '{0}'".format(name))

        # if actual renaming and not an initial naming
        if old_name is not None:
            new_data_dir = self.get_data_dir()
            # rename dir
            os.rename(old_data_dir, new_data_dir)

            # rename datafile (which is in newdatadir now)
            old_datafile = join_path(new_data_dir,
                                     old_datafile_name,
                                     ext=self.datafile_extension)
            new_datafile = self.get_datafile_fullpath()
            os.rename(old_datafile, new_datafile)
Example #17
0
 def init_settings():
     info_block("Loading settings...")
     if RelGlobals.settings_file() is None:
         raise AttributeError("settings_file attr not yet set in _RelGlobalContainer")
     try:
         with open(RelGlobals.settings_file(), "r") as f:
             dct = json.load(f)
     except FileNotFoundError:
         dct = _SettingsContainer._defaults
     for k,v in dct.items():
         setattr(_SettingsContainer, k, v)
Example #18
0
 def save_audio(self):
     """
     base wav audio saving. requires 'rate' and 'arr' attributes
     """
     info_block("saving audio of {0} '{1}'...".format(
         self.reltype, self.name))
     if self.arr is None:
         info_line("no audio to save...")
     else:
         sf.write(self.get_audiofile_fullpath(), self.arr,
                  self.rate.magnitude)
Example #19
0
 def info(self):
     """
     desc: display this objects data
     cat: info
     dev: essentially just an expanded repr. repr is also defined in super()
     """
     info_block("{0} '{1}'".format(self.reltype, self.name))
     info_line("sourced from {0}: {1}".format(self.source_block[0], self.source_block[1]))
     for ind in range(1, len(self.source_block) // 2):
         print("    {0}: {1}".format(self.source_block[2 * ind], self.source_block[2 * ind + 1]))
     info_line("parent: {0}".format(self.parent))
     info_line("rate: {0}".format(self.rate))
     info_line("size: {0:.4f}, {1:,}".format(self.size_secs(), self.size_samps()))
     info_line("pan: {0}".format(self.pan_val))
Example #20
0
 def init_globals():
     """
     read vars from data file
     """
     info_block("Loading global data...")
     if RelGlobals.data_file() is None:
         raise AttributeError("data_file attr not yet set in _RelGlobalContainer")
     try:
         with open(RelGlobals.data_file(), "r") as f:
             dct = json.load(f)
     except FileNotFoundError:
         dct = {i:getattr(_RelGlobalsContainer, i) for i in _RelGlobalsContainer._write_vars}
     for k,v in dct.items():
         setattr(_RelGlobalsContainer, k, v)
Example #21
0
 def list_samples(self):
     """
     desc: list samples in this sampler
     cat: info
     dev:
         returns bool, false if nothing to list
     """
     print("\n  Samples loaded into '{0}':".format(self.name))
     empty = True
     for obj in self.smps:
         info_list(str(obj))
         empty = False
     if empty:
         info_block("No samples loaded")
         return False
Example #22
0
 def list_rhythms(self):
     """
     desc: list rhythms in this sampler
     cat: info
     dev:
         returns bool, false if nothing to list
     """
     print("\n  Rhythms loaded into '{0}':".format(self.name))
     empty = True
     for obj in self.rhythms:
         empty = False
         info_list(str(obj))
     if empty:
         info_block("No rhythms loaded")
         return False
Example #23
0
 def see_proj(self, proj_name, proj_path):
     info_block("Previewing Project '{0}'".format(proj_name))
     fullpath = join_path(
         proj_path,
         proj_name + ".Project." + RelSavedObj.datafile_extension)
     with open(fullpath, "r") as f:
         data = json.load(f)
     info_title("Path: " + data["path"])
     info_line("Audio file: " + str(data["file"]))
     info_line("Children:")
     children = [
         re.sub(r"<.*>", "", i).split(".") for i in data["children"]
     ]
     children = ["{0} '{1}'".format(i[1], i[0]) for i in children]
     info_list(children)
Example #24
0
    def read_file(self, file_path=None):
        """
        reads files for recording object init
        takes multiple formats (via PyDub and Soundfile)
        updates self.source, self.arr, self.rate
        """
        if file_path is None:
            print("  Choose an input sound file...")
            time.sleep(1)
            file_path = input_file()

        info_block("Reading audio file...")
        t1 = time.time()

        # Handling file types
        _, _, ext = split_path(file_path)
        if ext != "wav":
            try:
                not_wav = pd.from_file(file_path, file_path.ext)
                not_wav.export(".temp_soundfile.wav", format="wav")
                file_path = ".temp_soundfile.wav"
            except FileNotFoundError:
                print("  > unable to find file '{0}'".format(file_path))
                print("  > make sure to include .wav/.mp3/etc extension")
                return self.read_file()

        # self.source_block["file"] = file_path
        # Reading and Processing File
        try:
            self.arr, rate = sf.read(file_path)
            self.rate = Units.rate(rate)
        except RuntimeError:
            print(
                "  > unable to find or read '{0}'. Is that the correct extension?"
                .format(file_path))
            return self.read_file()
        try:
            os.remove(".temp_soundfile.wav")
        except FileNotFoundError:
            pass
        if len(self.arr.shape) < 2:
            self.arr = NpOps.stereoify(self.arr)
        t2 = time.time()
        info_line(
            "sound file '{0}' read successfully in {1:.4f} seconds".format(
                file_path, t2 - t1))
Example #25
0
    def projects_menu(self):
        """
        top menu for opening or creating projects
        """
        while True:
            section_head("Projects Menu")

            # choose open type: open or create
            while self.current_open_proj is None:
                if bool(self.projects):
                    p("Open existing project (O) or Create new (C)?")
                    open_or_create = inpt("letter", allowed="oc")

                    if open_or_create == 'c':
                        self.create_proj()
                    else:
                        self.open_proj()
                else:
                    info_block(
                        "No existing projects. Defaulting to create new")
                    self.create_proj()

            self.process_project()
Example #26
0
    def options(self):
        """
        cat: info
        desc: list all process options that can be run on this object (shortcut 'o')
        """
        nl()
        with style("cyan"):
            info_block("{CATEGORY}", indent=2)
        info_line("- {Process}")
        info_line("{arguments in order, optional if in [square brackets]}",
                  indent=8)
        nl()

        meths = {}
        for mth in self.get_all_public_methods():
            cat = get_reldata(mth, "category")
            try:
                meths[cat].append(mth)
            except KeyError:
                meths[cat] = [mth]

        categories = list(meths.keys())
        # sort by category.value, which is the string representation of that category
        categories.sort(key=lambda x: x.value)
        for cat in categories:
            with style("cyan"):
                info_line(cat.value.upper(), indent=2)
            for method in meths[cat]:
                method._rel_data.display()
            if cat == Category.PROPERTY:
                prop_names = self.get_all_prop_names()
                if not prop_names:
                    info_line("(no properties to edit)", indent=10)
                else:
                    for i in prop_names:
                        info_line("* " + i, indent=10)
Example #27
0
    def add_beats(self):
        """
        dev: create beats through prompts or pass 'beat' param to set (??)
        """
        info_block("Creating new Rhythm '{0}'".format(self.name))
        while True:
            info_block(
                "Enter a beat as <place in rhythm> <optional: length> ('q' to finish, 'i' for more info)",
                indent=2,
                hang=2,
                trailing_newline=False)
            print("  : ", end="")
            try:
                new_beat = inpt("split",
                                "beat",
                                help_callback=self.rhythms_help)
            except Cancel:
                info_block("Finished creating Rhythm '{0}'".format(self.name))
                return
            if not (1 <= len(new_beat) <= 2):
                err_mess(
                    "Wrong number of arguments! From 1 to 2 are required, {0} were supplied"
                    .format(len(new_beat)))
                continue
            if secs(new_beat[0]) >= secs(str(self.length) + 'b'):
                err_mess(
                    "This beat begins after the end of the rhythm! Try again")
                continue

            self.beats.append(new_beat)

            while len(new_beat) < 3:
                new_beat.append(0)
            if new_beat[1] == 0:
                new_beat[1] = "all"
            info_line("  Added beat - " + self.beat_repr(new_beat))
Example #28
0
 def get_frames_mono(self, **kwargs):
     info_block("Calculating frames...")
     return self.get_frames(self.mono_arr, **kwargs)
Example #29
0
 def get_frames_right(self, **kwargs):
     info_block("Calculating right channel frames...")
     return self.get_frames(self.arr[:, 1], **kwargs)
Example #30
0
 def debug_off():
     info_block("Debug is now off")
     _SettingsContainer.debug = False