Exemplo n.º 1
0
def ks_synth(freq):
    """
  Synthesize the given frequency into a Stream by using a model based on
  Karplus-Strong.
  """
    ks_mem = (sum(lz.sinusoid(x * freq) for x in [1, 3, 9]) +
              lz.white_noise() + lz.Stream(-1, 1)) / 5
    return lz.karplus_strong(freq, memory=ks_mem)
def m21_to_stream(score,
                  synth=ks_synth,
                  beat=90,
                  fdur=2.,
                  pad_dur=.5,
                  rate=lz.DEFAULT_SAMPLE_RATE):
    """
  Converts Music21 data to a Stream object.

  Parameters
  ----------
  score :
    A Music21 data, usually a music21.stream.Score instance.
  synth :
    A function that receives a frequency as input and should yield a Stream
    instance with the note being played.
  beat :
    The BPM (beats per minute) value to be used in playing.
  fdur :
    Relative duration of a fermata. For example, 1.0 ignores the fermata, and
    2.0 (default) doubles its duration.
  pad_dur :
    Duration in seconds, but not multiplied by ``s``, to be used as a
    zero-padding ending event (avoids clicks at the end when playing).
  rate :
    The sample rate, given in samples per second.

  """
    # Configuration
    s, Hz = lz.sHz(rate)
    step = 60. / beat * s

    # Creates a score from the music21 data
    score = reduce(
        operator.concat,
        [
            [
                (
                    pitch.frequency * Hz,  # Note
                    note.offset * step,  # Starting time
                    note.quarterLength * step,  # Duration
                    Fermata in note.expressions) for pitch in note.pitches
            ] for note in score.flat.notes
        ])

    # Mix all notes into song
    song = lz.Streamix()
    last_start = 0
    for freq, start, dur, has_fermata in score:
        delta = start - last_start
        if has_fermata:
            delta *= 2
        song.add(delta, synth(freq).limit(dur))
        last_start = start

    # Zero-padding and finishing
    song.add(dur + pad_dur * s, lz.Stream([]))
    return song
Exemplo n.º 3
0
def splitter(lines, sep="-=", keep_idx=False):
  """
  Splits underlined blocks without indentation (reStructuredText pattern).

  Parameters
  ----------
  lines :
    A list of strings
  sep :
    Underline symbols. A line with only such symbols will be seen as a
    underlined one.
  keep_idx :
    If False (default), the function returns a collections.OrderedDict. Else,
    returns a
    list of index pairs

  Returns
  -------
  A collections.OrderedDict instance where a block with underlined key like
  ``"Key\\n==="`` and a list of lines following will have the item (key, list
  of lines), in the order that they appeared in the lists input. Empty keys
  gets an order numbering, and might happen for example after a ``"----"``
  separator. The values (lists of lines) don't include the key nor its
  underline, and is also stripped/trimmed as lines (i.e., there's no empty
  line as the first and last list items, but first and last line may start/end
  with whitespaces).

  """
  separators = audiolazy.Stream(
                 idx - 1 for idx, el in enumerate(lines)
                         if all(char in sep for char in el)
                         and len(el) > 0
               ).append([len(lines)])
  first_idx = separators.copy().take()
  blk_data = OrderedDict()

  empty_count = iter(audiolazy.count(1))
  next_empty = lambda: "--Empty--{0}--".format(next(empty_count))

  if first_idx != 0:
    blk_data[next_empty()] = lines[:first_idx]

  for idx1, idx2 in separators.blocks(size=2, hop=1):
    name = lines[idx1].strip() if lines[idx1].strip() != "" else next_empty()
    blk_data[name] = lines[idx1+2 : idx2]

  # Strips the empty lines
  for name in blk_data:
    while blk_data[name][-1].strip() == "":
      blk_data[name].pop()
    while blk_data[name][0].strip() == "":
      blk_data[name] = blk_data[name][1:]

  return blk_data
Exemplo n.º 4
0
def pre_processor(app, what, name, obj, options, lines,
                  namer=lambda name: ":obj:`{0}`".format(name)):
  """
  Callback preprocessor function for docstrings.
  Converts data from Spyder pattern to Sphinx, using a ``namer`` function
  that defaults to ``lambda name: ":obj:`{0}`".format(name)`` (specific for
  ``.. seealso::``).

  """
  # Duplication removal
  if what == "module": # For some reason, summary appears twice
    idxs = [idx for idx, el in enumerate(lines) if el.startswith("Summary")]
    if len(idxs) >= 2:
      del lines[idxs.pop():] # Remove the last summary
    if len(idxs) >= 1:
      lines.insert(idxs[-1] + 1, "")
      if obj is audiolazy.lazy_math:
        lines.insert(idxs[-1] + 1, ".. tabularcolumns:: cl")
      else:
        lines.insert(idxs[-1] + 1, ".. tabularcolumns:: CJ")
      lines.insert(idxs[-1] + 1, "")

  # Real docstring format pre-processing
  result = []
  for name, blk in iteritems(splitter(lines)):
    nlower =  name.lower()

    if nlower == "parameters":
      starters = audiolazy.Stream(idx for idx, el in enumerate(blk)
                                      if len(el) > 0
                                      and not el.startswith(" ")
                                 ).append([len(blk)])
      for idx1, idx2 in starters.blocks(size=2, hop=1):
        param_data = " ".join(b.strip() for b in blk[idx1:idx2])
        param, expl = param_data.split(":", 1)
        if "," in param:
          param = param.strip()
          if not param[0] in ("(", "[", "<", "{"):
            param = "[{0}]".format(param)
        while "," in param:
          fparam, param = param.split(",", 1)
          result.append(":param {0}: {1}".format(fparam.strip(), "\.\.\."))
        result.append(":param {0}: {1}".format(param.strip(), expl.strip()))

    elif nlower == "returns":
      result.append(":returns: " + " ".join(blk))

    elif nlower in ("note", "warning", "hint"):
      result.append(".. {0}::".format(nlower))
      result.extend("  " + el for el in blk)

    elif nlower == "examples":
      result.append("**Examples**:")
      result.extend("  " + el for el in blk)

    elif nlower == "see also":
      result.append(".. seealso::")
      for el in blk:
        if el.endswith(":"):
          result.append("") # Skip a line
           # Sphinx may need help here to find some object locations
          refs = [namer(f.strip()) for f in el[:-1].split(",")]
          result.append("  " + ", ".join(refs))
        else:
          result.append("  " + el)

    else: # Unkown block name, perhaps the starting one (empty)
      result.extend(blk)

    # Skip a line after each block
    result.append("")

  # Replace lines with the processed data while keeping the actual lines id
  del lines[:]
  lines.extend(result)