Ejemplo n.º 1
0
def _partition_fib(n: int, numpartitions: int, homogeneity=0.) -> List[int]:
    """
    if homogeneity == 0: the partitions build a fib curve, which means that if

    s = partition_fib(n, partitions, homogeneity=0), then

    all(s[i] + s[i+1] == s[i+2] for i in range(len(s-2))) is True

    if homogeneity == 1: the partitions build a linear curve

    first a fib curve is built, then an interpolation between this curve
    and a linear curve is done
    """
    assert 0 <= homogeneity <= 1
    if numpartitions > 60:
        raise ValueError("Two many partitions. Max n == 60")
    n0 = 10
    n1 = n0 + numpartitions
    fib_numbers = list(map(interpol.fib, list(range(n0, n1))))
    sum_fibs = sum(fib_numbers)
    normalized_fibs = [(x - 0) / sum_fibs * n for x in fib_numbers]
    avg_y = n / numpartitions
    partitions = [bpf.linear(0, 1, y, avg_y)(homogeneity) for y in normalized_fibs]
    assert all(partition >= 0 for partition in partitions)
    assert abs(sum(partitions) - n) < 0.0001, partitions
    return sorted(partitions)
Ejemplo n.º 2
0
def interleave(A, B, weight=0.5):
    """
    interleave the elements of A and B
    weight: 0-1
            0   -> first the elements of xs, then B, not interleaved
            0.5 -> interleave A and B regularly
            1   -> first the elements of B, then A
    """
    if not B:
        return A
    elif not A:
        return B
    c = bpf.linear(0, len(A), 0.5, len(A)/len(B), 1, 1/len(A))
    r = xr = c(weight)
    out = []
    L = len(A)+len(B)
    A_index = 0
    B_index = 0

    while True:
        if r >= 1:
            if A_index < len(A):
                out.append(A[A_index])
                A_index += 1
            r -= 1
        else:
            if B_index < len(B):
                out.append(B[B_index])
                B_index += 1
            r += xr
        if len(out) == L:
            break
    return out
Ejemplo n.º 3
0
def _test_distribute_weighted_streams():
    A = "AAAAAAAAAAAAAAAAAAAAAAAA"
    C = "CCCCC"
    D = "DDD"

    streams = (A, C, D)
    stream_quantities = (len(A), len(C), len(D))
    weight_bpfs = (bpf.linear(0, 1, 1, 1),     # bpfs must be defined within the unity
                   bpf.halfcos(0, 0, 0.5, 1, 1, 0),
                   bpf.expon(0, 0, 1, 1, exp=3)
                   )
    distributed_frames = distribute_weighted_streams(stream_quantities, weight_bpfs)
    for frame in distributed_frames:
        print(streams[frame.stream][frame.index_in_stream])
Ejemplo n.º 4
0
def criticalband(freq):
    # type: (float) -> float
    """
    Equivalent Rectangular Bandwidth as a function
    of Centre Frequency (in Hz)

    http://web.mit.edu/HST.723/www/ThemePapers/Masking/Moore95.pdf
    """
    moore95 = _curves.get('moore95')
    if not moore95:
        moore95 = bpf.linear(30, 30, 100, 35, 200, 45, 300, 50, 500, 70, 1000,
                             110, 2000, 220, 3000, 500, 10000,
                             900).keep_skope()
        _curves['moore95'] = moore95
    band = moore95(freq)  # type: float
    return band
Ejemplo n.º 5
0

def plot_pyplot(partials, size=20, alpha=0.5, downsample=1, kind='amp', **kws):
    from matplotlib import pyplot as plt
    fig, ax = plt.subplots(1, 1)
    if kind == 'amp':
        for p in partials:
            _pyplot_plot_partial_amp(p, ax, size, alpha, downsample=downsample)
    elif kind == 'bw':
        for p in partials:
            _pyplot_plot_partial_bw(p, ax, size, alpha, downsample=downsample)
    plt.show()
    return True


_pyplot_colorcurve_amp = bpf.linear(-90, 0.8, -30, 0.3, -6, 0.1, 0, 0)
_pyplot_colorcurve_bw = bpf.linear(0, 0.15, 0.5, 0.3, 0.9, 0.5, 0.95, 0.8, 1, 0.99)


def _pyplot_plot_partial_amp(partial: _partial.Partial, ax, size=20.0, alpha=0.5,
                             downsample:int=1):
    X = partial.times     # type: np.ndarray
    Y = partial.freqs     # type: np.ndarray
    amps = partial.amps   # type: np.ndarray
    if downsample > 1:
        X = X[::downsample]
        Y = Y[::downsample]
        amps = amps[::downsample]
    dbs = amp2db_np(amps)
    colorcurve = _pyplot_colorcurve_amp
    Z = colorcurve.map(dbs, out=dbs)
Ejemplo n.º 6
0
    def bpfs():
        y = 1.5
        b = bpf4.linear(0, y, 1, y, 10, y, 10.01, y, 10.010001, y, 20, y)
        yield b

        yield bpf4.linear(-1, 10, 1, 10, 10000, 10)
Ejemplo n.º 7
0
class XmlNotehead(NamedTuple):
    shape: str
    filled: bool


MUSICXML_NOTEHEADS = [
    XmlNotehead("normal", filled=False),
    XmlNotehead("square", filled=False),
    XmlNotehead("diamond", filled=False),
    XmlNotehead("harmonic", filled=False),
    XmlNotehead("x", filled=False),
    XmlNotehead("circle-x", filled=False)
]  # type: List[XmlNotehead]


bw_to_noteheadindex = bpf.linear(0, 0, 1, len(MUSICXML_NOTEHEADS)-1)


# exactitud de la grid en la traduccion a musicxml
# lcm(3, 4, 5, 6, 7, 8, 9, 10, 12, 14, 16, 20, 32)
# No puede representar exactamente tuples de 11, 13, 17
MUSICXML_DIVISIONS = 10080
MUSICXML_TENTHS = 40
DEFAULT_POSSIBLE_DIVISIONS = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12)


IRREGULAR_TUPLES = (
    (5, 6),
    (5, 7),
    (5, 8),
    (5, 9),
Ejemplo n.º 8
0
    endin
    """
    return template.format(name=name, audiogen=audiogen)


def _get_possible_instrs(orc=None):
    matches = re.findall(r"\binstr\s+\b\S+\b", _orc)
    return [match.split()[1] for match in matches]


_possible_instrs = _get_possible_instrs()

_db2vel = bpf.linear(
    -120, 0,
    -90, 10,
    -70, 20,
    -24, 90,
    0, 127
)

def makeScoreLine(instr:str, start:float, dur:float,
                  pitch1:float, pitch2:float, ampdB:float,
                  comment:str='') -> str:
    commentStr = '' if not comment else f";  {comment}"
    return f'i "{instr}"\t{start:.6f}\t{dur:.6f}\t{pitch1}\t{pitch2}\t{ampdB}\t\t {commentStr}'


def csoundScoreForPart(part: Part, defaultInstr='piano',
                       allowDiscontinuousGliss=True, defaultGain=0.5) -> List[str]:
    # TODO
    pass
Ejemplo n.º 9
0
    def bpfs():
        y = 1.5
        b = bpf4.linear(0, y, 1, y, 10, y, 10.01, y, 10.010001, y, 20, y)
        yield b

        yield bpf4.linear(-1, 10, 1, 10, 10000, 10)
Ejemplo n.º 10
0
import sndtrck
import bpf4 as bpf
from emlib.pitchtools import *
from emlib.iterlib import pairwise, flatten
from emlib.distribute import dohndt

from .track import Track
from .config import RenderConfig
from .envir import logger
from .typehints import *

from functools import lru_cache

_default = {
    'freq2points':
    bpf.linear(0, 0.00001, 20, 5, 50, 100, 400, 100, 800, 80, 2800, 80, 3800,
               50, 4500, 10, 5000, 0),
    'amp2points':
    bpf.linear(-90, 0.00001, -60, 2, -35, 40, -12, 95, 0, 100),
    'dur2points':
    bpf.linear(0, 0.0001, 0.1, 5, 0.3, 20, 0.5, 40, 2, 70, 5, 100),
    'harmonicity_gain':
    bpf.linear(0.7, 1, 1, 2),
    'overtone_gain':
    bpf.linear(1, 1.5, 5, 1)
}


def _asbpf(obj):
    if isinstance(obj, dict):
        return bpf.util.dict_to_bpf(obj)
    elif isinstance(obj, list):
Ejemplo n.º 11
0
def mincer(sndfile, timecurve, pitchcurve, outfile=None, dt=0.002, 
           lock=False, fftsize=2048, ksmps=128, debug=False):
    """
    sndfile: the path to a soundfile
    timecurve: a bpf mapping time to playback time or a scalar indicating a timeratio
               (2 means twice as fast)
               1 to leave unmodified
    pitchcurve: a bpf mapping x=time, y=pitchscale. or a scalar indicating a freqratio
                (2 means an octave higher) 
                1 to leave unmodified

    outfile: the path to a resulting outfile

    Returns: a dictionary with information about the process 

    NB: if the mapped time excedes the bounds of the sndfile,
        silence is generated. For example, a negative time
        or a time exceding the duration of the sndfile

    NB2: the samplerate and number of channels of of the generated file matches 
         that of the input file

    NB3: the resulting file is always a 32-bit float .wav file

    ** Example 1: stretch a soundfile 2x

       timecurve = bpf.linear(0, 0, totaldur*2, totaldur)
       outfile = mincer(sndfile, timecurve, 1)
    """
    import bpf4 as bpf
    import sndfileio
    
    if outfile is None:
        outfile = filetools.addSuffix(sndfile, "-mincer")
    info = sndfileio.sndinfo(sndfile)
    sr = info.samplerate
    nchnls = info.channels
    pitchbpf = bpf.asbpf(pitchcurve)
    
    if isinstance(timecurve, (int, float)):
        t0, t1 = 0, info.duration / timecurve
        timebpf = bpf.linear(0, 0, t1, info.duration)
    elif isinstance(timecurve, bpf.core._BpfInterface):
        t0, t1 = timecurve.bounds()
        timebpf = timecurve
    else:
        raise TypeError("timecurve should be either a scalar or a bpf")
    
    assert isinstance(pitchcurve, (int, float, bpf.core._BpfInterface))
    ts = np.arange(t0, t1+dt, dt)
    fmt = "%.12f"
    _, time_gen23 = tempfile.mkstemp(prefix='time-', suffix='.gen23')
    np.savetxt(time_gen23, timebpf.map(ts), fmt=fmt, header=str(dt), comments="")
    _, pitch_gen23 = tempfile.mkstemp(prefix='pitch-', suffix='.gen23')
    np.savetxt(pitch_gen23, pitchbpf.map(ts), fmt=fmt, header=str(dt), comments="")
    if outfile is None:
        outfile = filetools.addSuffix(sndfile, '-mincer')
    csd = f"""
    <CsoundSynthesizer>
    <CsOptions>
    -o {outfile}
    </CsOptions>
    <CsInstruments>

    sr = {sr}
    ksmps = {ksmps}
    nchnls = {nchnls}
    0dbfs = 1.0

    gi_snd   ftgen 0, 0, 0, -1,  "{sndfile}", 0, 0, 0
    gi_time  ftgen 0, 0, 0, -23, "{time_gen23}"
    gi_pitch ftgen 0, 0, 0, -23, "{pitch_gen23}"

    instr vartimepitch
        idt tab_i 0, gi_time
        ilock = {int(lock)}
        ifftsize = {fftsize}
        ikperiod = ksmps/sr
        isndfiledur = ftlen(gi_snd) / ftsr(gi_snd)
        isndchnls = ftchnls(gi_snd)
        ifade = ikperiod*2
        inumsamps = ftlen(gi_time)
        it1 = (inumsamps-2) * idt           ; account for idt and last value
        kt timeinsts
        aidx    linseg 1, it1, inumsamps-1
        at1     tablei aidx, gi_time, 0, 0, 0
        kpitch  tablei k(aidx), gi_pitch, 0, 0, 0
        kat1 = k(at1)
        kgate = (kat1 >= 0 && kat1 <= isndfiledur) ? 1 : 0
        agate = interp(kgate) 
        aenv linseg 0, ifade, 1, it1 - (ifade*2), 1, ifade, 0
        aenv *= agate
        if isndchnls == 1 then
            a0  mincer at1, 1, kpitch, gi_snd, ilock, ifftsize, 8
            outch 1, a0*aenv
        else
            a0, a1   mincer at1, 1, kpitch, gi_snd, ilock, ifftsize, 8
            outs a0*aenv, a1*aenv
        endif
        
      if (kt >= it1 + ikperiod) then
        event "i", "exit", 0.1, 1
            turnoff     
        endif
    endin

    instr exit
        puts "exiting!", 1
        exitnow
    endin

    </CsInstruments>
    <CsScore>
    i "vartimepitch" 0 -1
    f 0 36000

    </CsScore>
    </CsoundSynthesizer>
    """
    _, csdfile = tempfile.mkstemp(suffix=".csd")
    with open(csdfile, "w") as f:
        f.write(csd)
    subprocess.call(["csound", "-f", csdfile])
    if not debug:
        os.remove(time_gen23)
        os.remove(pitch_gen23)
        os.remove(csdfile)
    return {'outfile': outfile, 'csdstr': csd, 'csd': csdfile}
Ejemplo n.º 12
0
def make_weighter(mode='speech'):
    if mode == 'speech':
        freqcurve = bpf.linear(0, 0, 50, 0, 80, 1, 200, 1, 250, 2, 4500, 2, 6000, 1, 8000, 1, 10000, 0)
        durcurve = bpf.linear(0, 0, 0.01, 0, 0.02, 1)
        ampcurve = bpf.linear(0, 0, db2amp(-75), 0, db2amp(-65), 1)
    elif mode == 'transcription':
        freqcurve = bpf.linear(0, 0, 30, 0, 50, 1, 4500, 1, 5000, 0)
        durcurve = bpf.linear(0, 0, 0.01, 0, 0.02, 1)
        ampcurve = bpf.linear(0, 0, db2amp(-70), 0, db2amp(-60), 1)
    elif mode == 'default':
        freqcurve = bpf.linear(0, 0, 30, 0, 50, 1, 8000, 1, 12000, 0.5, 16000, 0)
        durcurve = bpf.linear(0, 0, 0.01, 0, 0.02, 1)
        ampcurve = bpf.linear(0, 0, db2amp(-80), 0, db2amp(-60), 1)
    elif mode == 'speech-transcription':
        freqcurve = bpf.linear(0, 0, 50, 0, 80, 1, 200, 1, 250, 2, 4500, 2, 5000, 0)
        durcurve = bpf.linear(0, 0, 0.01, 0, 0.02, 1)
        ampcurve = bpf.linear(0, 0, db2amp(-75), 0, db2amp(-65), 1)
    else:
        raise KeyError("mode unknown, must be one of 'speech', 'transcription'")
    return PartialWeighter(freqcurve=freqcurve, durcurve=durcurve, ampcurve=ampcurve, 
                           freqweight=1, durweight=1, ampweight=2)