Ejemplo n.º 1
0
def _note_deviates(b0, b1, b2, pitchdelta: float, dbdelta: float):
    """
    True if b1 deviates from the interpolation of b0 and b2

    dbdelta and pitchdelta can be negative, in which case they are not taken into account
    
    bx: a tuplet of (time, freq, amp, ...)
    """
    t0 = b0[0]
    t = b1[0]
    t1 = b2[0]
    dt = (t - t0) / (t1 - t0)
    if dbdelta >= 0:
        a0 = b0[2]
        a = b1[2]
        a1 = b2[2]
        a_t = a0 + dt * (a1 - a0)
        if abs(amp2db(a) - amp2db(a_t)) >= dbdelta:
            return True
    if pitchdelta >= 0:
        f0 = b0[1]
        f = b1[1]
        f1 = b2[1]
        f_t = f0 + dt * (f1 - f0)
        if abs(f2m(f_t) - f2m(f)) >= pitchdelta:
            return True
    return False
Ejemplo n.º 2
0
 def atx(self, time: float, freqs: _S[float]) -> _S[float]:
     s = self.sp.partials_at(time)
     data = [(p.freq(time), p.amp(time)) for p in s]
     data.sort()
     out = []
     d = self.decay
     mindb = self.mindb
     for freq in freqs:
         idx1 = bisect.bisect(data, (freq, 0))
         if idx1 >= len(data):
             idx1 = idx0 = idx1 - 1
         idx0 = max(0, idx1 - 1)
         f0, a0 = data[idx0]
         f1, a1 = data[idx1]
         a0db = amp2db(a0)
         a1db = amp2db(a1)
         df0 = (a0db - mindb) / d
         df1 = (a1db - mindb) / d
         if f1 - df1 <= freq <= f0 + df0:
             db0 = _linlin(freq, f0, f0 + df0, a0db, -120)
             db1 = _linlin(freq, f1 - df1, f1, -120, a1db)
             db = max(db0, db1)
         elif freq <= f0 + df0:
             db = _linlin(freq, f0, f0 + df0, a0db, -120)
         elif f1 - df1 <= freq:
             db = _linlin(freq, f1 - df1, f1, -120, a1db)
         else:
             db = mindb
         out.append(db2amp(db))
     return out
     """
Ejemplo n.º 3
0
 def amp2dyn(self, amp: float, nearest=True) -> str:
     """
     Convert amplitude to a string representation of its corresponding
     musical dynamic as defined in DYNAMIC_TABLE
     
     amp: an amplitude 0-1
     nearest: if True, find the nearest dynamic (can round up), 
         otherwise, the next lower dynamic
     """
     amps = self._amps
     dyns = self.dynamics
     if amp < amps[0]:
         return dyns[0]
     if amp > amps[-1]:
         return dyns[-1]
     insert_point = _bisect(amps, amp)
     if not nearest:
         floor = max(0, amps[insert_point - 1])
         return dyns[floor]
     if insert_point == 0:
         return dyns[0]
     if insert_point >= len(amps):
         return dyns[-1]
     assert 1 <= insert_point < len(amps)
     amp0, dyn0 = amps[insert_point - 1], dyns[insert_point - 1]
     amp1, dyn1 = amps[insert_point], dyns[insert_point]
     db = amp2db(amp)
     dyn = dyn0 if abs(db - amp2db(amp0)) < abs(db - amp2db(amp1)) else dyn1
     assert isinstance(dyn, str)
     return dyn
Ejemplo n.º 4
0
    def nearestx(self,
                 time: float,
                 freqs: _S[float],
                 timemargin=0.01) -> _S[float]:
        """
        Return a list of (freq, amp), representing the 
        freq and amp of the nearest Partial for each given freq.

        Example:

        freqs = [100, 200]
        out = surface.nearest(0.5, freqs)
        for freq, row in zip(freq, out):
            print(f"Nearest partial from {freq}Hz @ 0.5s has a freq. of {row[0]}")

        """
        s = self.sp.partials_between(time - timemargin, time + timemargin)
        if not s:
            return [(0, 0)] * len(freqs)
        data = [(p.freq(time), p.amp(time)) for p in s]
        mindb = self.mindb
        decay = self.decay
        out = []
        for freq in freqs:
            nearest = min(data, key=lambda row: abs(row[0] - freq))
            f, a = nearest
            db = amp2db(a)
            diff = abs(f - freq)
            db2 = max(db - diff * decay, mindb)
            out.append((f, db2amp(db2)))
        return out
Ejemplo n.º 5
0
def linearamp(amp:float, dbfloor:float=-100.0) -> float:
    """
    Converts an amplitude to a value between 0-1 following the dB scale

    dbfloor: min. amplitude as db
    """
    dbrange = abs(dbfloor)
    posdb = max(dbfloor, amp2db(amp)) + dbrange
    return posdb / dbrange
Ejemplo n.º 6
0
def _breakpoint_deviates(b0, b1, b2, dbdelta, pitchdelta, bwdelta):
    """
    True if b1 deviates from the interpolation of b0 and b2
    
    bx: a tuplet of (time, freq, amp, bw)
    """
    t0, f0, a0, bw0 = b0
    t, f, a, bw = b1
    t1, f1, a1, bw1 = b2
    a_t = interpol_linear(t, t0, a0, t1, a1)
    varamp = abs(amp2db(a) - amp2db(a_t))
    if varamp >= dbdelta:
        return True
    f_t = interpol_linear(t, t0, f0, t1, f1)
    varpitch = abs(f2m(f_t) - f2m(f))
    if varpitch >= pitchdelta:
        return True
    bw_t = interpol_linear(t, t0, bw0, t1, bw1)
    if abs(bw_t - bw) >= bwdelta:
        return True
    return False
Ejemplo n.º 7
0
    def amp2dyn(self, amp: float, nearest=True) -> str:
        """
        convert amplitude to a string representation of its corresponding
        musical dynamic as defined in DYNAMIC_TABLE

        nearest: if True, it searches for the nearest dynamic. Otherwise it gives 
                 the dynamic exactly inferior

       """
        curve = self._amps2dyns
        if amp < curve[0][0]:
            return curve[0][1]
        if amp > curve[-1][0]:
            return curve[-1][1]
        insert_point = _bisect(curve, (amp, None))
        if not nearest:
            idx = max(0, insert_point - 1)
            return curve[idx][1]
        amp0, dyn0 = curve[insert_point - 1]
        amp1, dyn1 = curve[insert_point]
        db = amp2db(amp)
        return dyn0 if abs(db - amp2db(amp0)) < abs(db -
                                                    amp2db(amp1)) else dyn1
Ejemplo n.º 8
0
 def nearest(self, time: float, freq: float, timemargin=0.01) -> float:
     s = self.sp.partials_between(time - timemargin, time + timemargin)
     if not s:
         return (0, 0)
     mindist = float("inf")
     for p in s:
         p_freq = p.freq(time)
         dist = abs(p_freq - freq)
         if dist < mindist:
             mindist = dist
             best_freq = p_freq
             best_partial = p
     best_amp = best_partial.amp(time)
     db = max(amp2db(best_amp) - mindist * self.decay, self.mindb)
     return best_freq, db2amp(db)
Ejemplo n.º 9
0
 def dyn2db(self, dyn: str) -> float:
     return amp2db(self.dyn2amp(dyn))
Ejemplo n.º 10
0
 def peak(self) -> float:
     """return the highest sample value (dB)"""
     return amp2db(np.abs(self.samples).max())