Ejemplo n.º 1
0
    def sliding_stretch(self, i_factor, f_factor, start=0, end=None):
        """
        cat: edit
        desc: stretch by sliding amount
        args:
            i_factor: initial factor, num >0; 0.2, 3;
            f_factor: final, num >0; 0.2, 3;
            [start: beat/second to begin. defaults beginning]
            [end: beat/second to end. defaults to end of rec]
        """
        i_factor = inpt_validate(i_factor, "flt", allowed=[0, None])
        f_factor = inpt_validate(f_factor, "flt", allowed=[0, None])
        start = inpt_validate(start, 'beatsec').to_samps()
        if end is None:
            end = self.size_samps()
        else:
            end = inpt_validate(end, 'beatsec').to_samps()
        print("  sliding stretch, from factor {0:.4f}x to {1:.4f}x...".format(i_factor, f_factor))
        beginning = self.arr[:start]

        middle = []
        factor_count = 0
        factor = i_factor
        delta_factor = (f_factor - i_factor) / ind(end - start)
        for i in self.arr[start:end]:
            factor_count += factor
            for _ in range(int(factor_count)):
                middle.append(i)
            factor_count = factor_count - int(factor_count)
            factor += delta_factor
        
        end = self.arr[end:]
        self.arr = np.vstack((beginning, middle, end))
Ejemplo n.º 2
0
    def set_length_and_period(self, length=None, period=None):
        """
        cat: edit
        desc: set the length and period of this rhythm. Give 0 for either argument to keep the current value
        args:
            length: length of the rhythm in beats
            period: standard subdivision of this rhythm, in beats
        """
        if length == 0 and self.length is not None:
            pass
        elif length is None:
            p("Enter a length in beats for this Rhythm")
            length = inpt('beats')
            if length != 0:
                self.length = length
            elif self.length is None:
                err_mess(
                    "There is no current value for length, enter a valid value in beats"
                )
                return self.set_length_and_period(None, period)
        else:
            self.length = inpt_validate(length, 'beats')

        if period == 0 and self.period is not None:
            pass
        elif period is None:
            p("Enter the period, or smallest beat that this Rhythm usually lands on",
              h=True)
            self.period = inpt('beat')
        else:
            self.period = inpt_validate(period, "beat")
Ejemplo n.º 3
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)
Ejemplo n.º 4
0
    def playback(self, duration=5, start=0, first_time=True):
        """
        cat: info
        desc: playback this recording's audio
        args:
            [duration: beats/seconds. default 5]
            [start: beat/seconds to start at. defualts to beginning]
        """
        duration = inpt_validate(duration, 'beatsec')
        start = inpt_validate(start, 'beatsec')
        section_head("Playback of '{0}'".format(self.name))

        print("  preparing...")
        start_ind = ind(start)
        if duration <= 0:
            end_ind = self.size_samps()
        else:
            end_ind = start_ind + ind(duration * self.rate)
        arr = self.arr[start_ind : end_ind]
        arr = self.get_panned_rec(arr)

        print("  playing...")
        rate = self.rate.to_rate().round().magnitude
        try:
            sd.play(arr, rate)
            sd.wait()
        except TypeError as e:
            if first_time:
                retry = True
                err_mess("Error playing back. Trying again")
                self.arr = [[float(i), float(j)] for i,j in self.arr]
                self.playback(duration, start, False)
            else:
                raise e
        print("  finished playback")
Ejemplo n.º 5
0
 def add(self, location, value):
     """
     cat: edit
     desc: add a new marker (see type_hint process for info on the specific types that arguments allow)
     args:
         location: the time where this marker should occur, in '{time_units}'
         value: the value of this marker, in/as a '{val_units}'
     dev: this docstring is .format()ed in init
     """
     beatsec = inpt_validate(location,
                             self.time_units,
                             allowed=self.time_allowed)
     value = inpt_validate(value, self.val_units, allowed=self.val_allowed)
     sample_ind = beatsec.to_samps()
     self.add_marker(sample_ind, DiscreteMarker(beatsec, value))
Ejemplo n.º 6
0
 def process_child(self, child_name=None):
     """
     cat: edit
     desc: edit a child member of this object
     args:
         [child_name: name of child to edit, omit to list children]
     """
     if len(self.children) == 0:
         err_mess("This Project has no children to process!")
     if child_name is None:
         self.list_children()
         p("Enter the name of the child you wish to edit")
         child_name = inpt("name")
     else:
         child_name = inpt_validate(child_name, "name")
     try:
         child_name = autofill(child_name, [i.name for i in self.children])
     except AutofillError as e:
         err_mess("Child name '{0}' not found".format(e.word))
         self.process_child()
         return
     child = None
     for i in self.children:
         if i.name == child_name:
             if child is not None:
                 raise UnexpectedIssue("Multiple children with name {0}".format(child_name))
             child = i
     process(child)
     child.save()
Ejemplo n.º 7
0
 def add(self, location, value, change_type=None):
     """
     cat: edit
     desc: add a new marker (see type_hint process for info on the specific types that arguments allow)
     args:
         location: the time where this marker should occur, in '{time_units}'
         value: the value of this marker, in/as '{val_units}'
         [change type: how the value transitions from the previous marker to this one, one of '{change_types}']
     dev: this docstring is .format()ed in init
     """
     beatsec = inpt_validate(location, self.time_units, self.time_allowed)
     sample_ind = beatsec.to_samps()
     value = inpt_validate(value, self.val_units, self.val_allowed)
     change_type = self.validate_change_type(change_type)
     self.add_marker(sample_ind,
                     ContinuousMarker(beatsec, value, change_type))
Ejemplo n.º 8
0
 def set(self, value):
     """
     cat: edit
     args:
         value: the new value of this property
     """
     value = inpt_validate(value, self.inpt_mode, self.allowed)
     setattr(self.caller, self.attrname(), value)
Ejemplo n.º 9
0
 def rename(self, name=None):
     if name is None:
         print("  Give this active pair a name: ", end="")
         name = inpt("obj")
         print("  named '{0}'".format(name))
     else:
         name = inpt_validate(name, "obj")
     self.name = name
Ejemplo n.º 10
0
 def repeat(self, times):
     """
     cat: edit
     args:
         times: integer number of times to repeat, >=1; 1, 10;
     """
     times = inpt_validate(times, 'int', allowed=[1, None])
     print("  repeating {0} times...".format(times))
     self.arr = np.vstack([self.arr] * times)
Ejemplo n.º 11
0
 def pan(self, amount):
     """
     cat: edit
     desc: set pan value
     args:
         amount: number from -1 (left) to 1 (right); -1, 1;
     """
     amount = inpt_validate(amount, 'float', allowed=[-1, 1])
     print("  Setting pan to {0}...".format(amount))
     self.pan_val = amount
Ejemplo n.º 12
0
 def amplify(self, factor):
     """
     cat: edit
     desc: multiply amplitude by factor. 0-1 to reduce, >1 to amplify
     args:
         factor: num >0; 0.5, 1.5;
     """
     factor = inpt_validate(factor, 'float', allowed=[0, 10])
     print("  amplifying by {0}x...".format(factor))
     self.arr *= factor
Ejemplo n.º 13
0
 def fade_in(self, dur, start=0):
     """
     cat: edit
     desc: fade in audio
     args:
         duration: duration in beats/seconds of fade-in; 0, 10;
         [start: beat/second to begin. defaults 0]
     """
     seconds = inpt_validate(dur, 'beatsec')
     start = ind(inpt_validate(start, 'beatsec'))
     print("  fading in {0} starting at {1}...".format(seconds, start))
     length = ind(self.rate * seconds)
     for i in range(length):
         try:
             self.arr[i + start][0] *= i / length
             self.arr[i + start][1] *= i / length
         except IndexError:
             if i + start >= 0:
                 return
Ejemplo n.º 14
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)
Ejemplo n.º 15
0
 def extend(self, length, placement="a"):
     """
     cat: edit
     desc: extend with silence by a number of seconds/beats
     args:
         length: beats/seconds to extend; 0, 1;
         [placement: "a"=after, "b"=before. default after]
     """
     length = inpt_validate(length, 'beatsec')
     placement = inpt_validate(placement, "letter", allowed="ab")
     if placement == "b":
         before = " before"
     else:
         before = ""
     print("  extending by {0}{1}...".format(length, before))
     silence = np.zeros( shape=(ind(self.rate * length), 2) )
     if placement == "b":
         self.arr = np.vstack((silence, self.arr))
     else:
         self.arr = np.vstack((self.arr, silence))
Ejemplo n.º 16
0
 def fade_out(self, dur, end=None):
     """
     cat: edit
     desc: fade out audio
     args:
         duration: duration in beats/seconds of fade-out; 0, 10;
         [end: beat/second to end. defaults end of audio]
     """
     if end is None:
         end = self.size_secs()
     else:
         end = inpt_validate(end, "beatsec")
     seconds = inpt_validate(dur, "beatsec")
     print("  Fading out {0} ending at {1}...".format(seconds, end))
     length = ind(self.rate * seconds)
     for i in range(ind(end) - length, ind(end)):
         try:
             self.arr[i][0] *= (length - i) / length
             self.arr[i][1] *= (length - i) / length
         except IndexError:
             pass
Ejemplo n.º 17
0
        def public_process_wrapper(*args):
            nonlocal allowed, modes
            allowed = _expand_ellipses(len(modes), allowed)

            func_args = [ args[0] ] # self as first arg
            for i in range(len(args) - 1):
                try:
                    mode = modes[i]
                except IndexError:
                    func_args.append(args[i+1])
                else:
                    val = inpt_validate(args[i+1], mode, allowed=allowed[i])
                    func_args.append(val)
            
            # do default args
            params = list(signature(method).parameters.values())
            for i in range(len(args) - 1, len(modes)):
                if params[i+1].default == Parameter.empty:
                    break
                val = inpt_validate(params[i+1].default, modes[i], allowed=allowed[i])
                func_args.append(val)

            return method(*func_args)
Ejemplo n.º 18
0
 def trim(self, left, right=None):
     """
     cat: edit
     desc: trim to only contain audio between <left> and <right>
     args:
         left: beat/second; 0, 5;
         [right: beat/second. defaults to end; 10, 20;]
     """
     left = inpt_validate(left, 'beatsec')
     if right is None:
         print("  trimming first {0}".format(left))
         right = self.size_samps()
     else:
         right = inpt_validate(right, 'beatsec')
         print("  trimming everything outside {0} to {1}".format(left, right))
     left, right = left.to_secs(), right.to_secs()
     if left * self.rate > self.size_samps():
         print("  > this will empty the recording, confirm? [y/n]: ", end="")
         if not inpt("yn"):
             return
         self.arr = np.empty(shape=(0,2))
     else:
         self.arr = self.arr[ind(left * self.rate) : ind(right * self.rate)]  
Ejemplo n.º 19
0
 def move(self, current, new):
     """
     cat: edit
     desc: move a marker to a new location
     Args:
         current: the beat or sec of the marker to move
         new: the beat or sec to move it to
     """
     old_beatsec = inpt_validate(current,
                                 self.time_units,
                                 allowed=self.time_allowed)
     new_beatsec = inpt_validate(new,
                                 self.time_units,
                                 allowed=self.time_allowed)
     old_sample_ind = old_beatsec.to_samps()
     new_samp_ind = new_beatsec.to_samps()
     try:
         marker = self.markers[old_sample_ind]
     except KeyError:
         err_mess("No marker to move at {0}!".format(old_beatsec))
         return
     marker.beatsec = new_beatsec
     self.add_marker(new_samp_ind, marker)
     del self.markers[old_sample_ind]
Ejemplo n.º 20
0
 def delete(self, location):
     """
     cat: edit
     desc: delete a marker from this controller
     args:
         location: beat or sec of the marker to remove
     """
     beatsec = inpt_validate(location,
                             self.time_units,
                             allowed=self.time_allowed)
     sample_ind = beatsec.to_samps()
     try:
         marker = self.markers[sample_ind]
         info_line("Deleting marker '{0}'".format(marker))
         del self.markers[sample_ind]
     except KeyError:
         err_mess("No marker to delete at {0}".format(beatsec))
Ejemplo n.º 21
0
 def process_child_sample(self, name=None):
     """
     desc: process a sample contained in this group
     """
     while True:
         if name is None:
             self.list_samples()
             p("Enter the name of the Sample to process")
             name = inpt('name')
         else:
             name = inpt_validate(name, 'name')
         try:
             self.samples[name]
             break
         except KeyError:
             err_mess("> Sample '{0}' does not exist!".format(name))
     process(self.samples[name])
Ejemplo n.º 22
0
 def stretch(self, factor):
     """
     cat: edit
     desc: stretch by a factor
     args:
         factor: number >0; 0.2, 3
     """
     factor = inpt_validate(factor, 'float', allowed=[0, None])
     print("  stretching by a factor of {0:.4f}...".format(factor))
     new_rec = []
     factor_count = 0
     for i in self.arr:
         factor_count += factor
         for _ in range(int(factor_count)):
             new_rec.append(i)
         factor_count -= int(factor_count)
     self.arr = np.asarray(new_rec)
Ejemplo n.º 23
0
 def set_variability(self, var=None):
     if var is None:
         p("Enter the variability (in percentage, 0-100%) of this Rhythm")
         self.variability = inpt('pcnt')
     else:
         self.variability = inpt_validate(var, 'pcnt')
Ejemplo n.º 24
0
 def validate_value(self, value):
     return inpt_validate(value, 'pcnt')
Ejemplo n.º 25
0
 def __set__(self, instance, value):
     if not isinstance(value, (Units.Quant, Controller)):
         value = inpt_validate(value, self.inpt_mode, self.allowed)
     setattr(instance, self.attrname(), value)