The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

Music::CreatingRhythms - Combinatorial algorithms to generate rhythms

VERSION

version 0.0700

SYNOPSIS

  use Music::CreatingRhythms ();
  my $mcr = Music::CreatingRhythms->new;
  my $foo = $mcr->foo('...');

DESCRIPTION

Music::CreatingRhythms provides the combinatorial algorithms described in the book, "Creating Rhythms", by Hollos. Many of these algorithms are ported directly from the C, and are pretty fast. Please see the links below for more information.

NB: Arguments are sometimes switched between book and software.

Additionally, this module provides utilities that are not part of the book, but are nonetheless handy.

ATTRIBUTES

verbose

  $verbose = $mcr->verbose;

Show progress. * This is not showing anything yet, however.

METHODS

new

  $mcr = Music::CreatingRhythms->new;

Create a new Music::CreatingRhythms object.

b2int

  $intervals = $mcr->b2int($sequences);

Convert binary sequences of the form [[1,0],[1,0,0]] into a set of intervals of the form [[2],[3]].

Examples:

  $got = $mcr->b2int([[1,1,0,1,0,0]]);     # [[1,2,3]]
  $got = $mcr->b2int([[1],[1,0],[1,0,0]]); # [[1],[2],[3]]

cfcv

  $convergent = $mcr->cfcv(@terms);

Calculate a continued fraction convergent given the terms.

Examples:

  $got = $mcr->cfcv(1, 2);       # [3,2]
  $got = $mcr->cfcv(1, 2, 2);    # [7,5]
  $got = $mcr->cfcv(1, 2, 2, 2); # [17,12]

cfsqrt

  $terms = $mcr->cfsqrt($n);
  $terms = $mcr->cfsqrt($n, $m);

Calculate the continued fraction for sqrt(n) to m digits, where n and m are integers.

Examples:

  $got = $mcr->cfsqrt(2, 2); # [1,2]
  $got = $mcr->cfsqrt(2, 3); # [1,2,2]
  $got = $mcr->cfsqrt(2, 4); # [1,2,2,2]

chsequl

  $sequence = $mcr->chsequl($t, $p, $q);
  $sequence = $mcr->chsequl($t, $p, $q, $n);

Generate the upper or lower Christoffel word for p and q.

Arguments:

  t: required type of word (u: upper, l: lower)
  p: required numerator of slope
  q: required denominator of slope
  n: optional number of terms to generate, default: p+q

Examples:

  $got = $mcr->chsequl('l', 11, 5);
  # [0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,1]
  $got = $mcr->chsequl('u', 11, 5);
  # [1,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0]
  $got = $mcr->chsequl('l', 11, 5, 4); # [0,1,1,0];
  $got = $mcr->chsequl('u', 11, 5, 4); # [1,1,1,0];

comp

  $compositions = $mcr->comp($n);

Generate all compositions of n.

A "composition" is the set of combinatorial "variations" of the partitions of n with the duplicates removed.

Example:

  $got = $mcr->comp(4);
  # [1,1,1,1],[1,1,2],[1,2,1],[1,3],[2,1,1],[2,2],[3,1],[4]

compa

  $compositions = $mcr->compa($n, @intervals);

Generate compositions of n with allowed intervals p1, p2, ... pn.

Here, the "intervals" are the terms of the partition.

Example:

  $got = $mcr->compa(4, 1,2);
  # [[1,1,1,1],[1,1,2],[1,2,1],[2,1,1],[2,2]]

compam

  $compositions = $mcr->compam($n, $m, @intervals);

Generate compositions of n with m parts and allowed intervals p1, p2, ... pn.

Here, the "parts" are the number of elements of each interval set.

Example:

  $got = $mcr->compam(4, 3, 1,2); # [[1,1,2],[1,2,1],[2,1,1]]

compm

  $compositions = $mcr->compm($n, $m);

Generate all compositions of n into m parts.

Again, the "parts" are the number of elements of each interval set.

Example:

  $got = $mcr->compm(4, 2); # [[1,3],[2,2],[3,1]]

compmrnd

  $composition = $mcr->compmrnd($n);

Generate a random composition of n.

Example:

  $got = $mcr->compmrnd(16, 4); # [6,1,3,6], etc.

comprnd

  $composition = $mcr->comprnd($n);

Generate a random composition of n.

Example:

  $got = $mcr->comprnd(16); # [1,3,2,1,1,2,1,3,2], etc.

count_ones

  $count = $mcr->count_ones($n);

Count the number of 1s in a string or vector.

Examples:

  $got = $mcr->count_ones('100110100');         # 4
  $got = $mcr->count_ones([1,0,0,1,1,0,1,0,0]); # 4

count_zeros

  $count = $mcr->count_zeros($n);

Count the number of 0s in a string or vector.

Examples:

  $got = $mcr->count_zeros('100110100');         # 5
  $got = $mcr->count_zeros([1,0,0,1,1,0,1,0,0]); # 5

de_bruijn

  $sequence = $mcr->de_bruijn($n);

Generate the largest de Bruijn sequence of order n.

Example:

  $got = $mcr->de_bruijn(3); # [1,1,1,0,1,0,0,0]

euclid

  $sequence = $mcr->euclid($n, $m);

Generate a Euclidean rhythm given n onsets distributed over m beats.

Examples:

  $got = $mcr->euclid(1, 4); # [1,0,0,0]
  $got = $mcr->euclid(2, 4); # [1,0,1,0]
  $got = $mcr->euclid(3, 4); # [1,1,0,1]
  $got = $mcr->euclid(4, 4); # [1,1,1,1]

int2b

  $sequences = $mcr->int2b($intervals);

Convert intervals of the form [2,3] into a set of binary sequences.

Examples:

  $got = $mcr->int2b([[1,2,3]]);     # [[1,1,0,1,0,0]]
  $got = $mcr->int2b([[1],[2],[3]]); # [[1],[1,0],[1,0,0]]

invert_at

  $sequence = $mcr->invert_at($n, $parts);

Invert a section of a parts binary sequence at n.

Examples:

    $parts = [qw(1 0 1 0 0)];
    $got = $mcr->invert_at(0, $parts); # [0,1,0,1,1]
    $got = $mcr->invert_at(1, $parts); # [1,1,0,1,1]
    $got = $mcr->invert_at(2, $parts); # [1,0,0,1,1]

neck

  $necklaces = $mcr->neck($n);

Generate all binary necklaces of length n.

Example:

  $got = $mcr->neck(3); # [1,1,1],[1,1,0],[1,0,0],[0,0,0]

necka

  $necklaces = $mcr->necka($n, @intervals);

Generate binary necklaces of length n with allowed intervals p1, p2, ... pn. For these "necklace" class of functions, the word "intervals" refers to the size of a number given trailing zeros. So intervals 1, 2, and 3 are represented as 1, 1,0, and 1,0,0 respectively.

Example:

  $got = $mcr->necka(4, 1,2); # [1,1,1,1],[1,1,1,0],[1,0,1,0]

neckam

  $necklaces = $mcr->neckam($n, $m, @intervals);

Generate binary necklaces of length n with m ones, and allowed intervals p1, p2, ... pn.

Example:

  $got = $mcr->neckam(4, 3, 1,2); # [[1,1,1,0]]

neckm

  $necklaces = $mcr->neckm($n, $m);

Generate all binary necklaces of length n with m ones.

Example:

  $got = $mcr->neckm(4, 2); # [[1,1,0,0],[1,0,1,0]]

part

  $partitions = $mcr->part($n);

Generate all partitions of n.

Example:

  $got = $mcr->part(4); # [1,1,1,1],[1,1,2],[2,2],[1,3],[4]

parta

  $partitions = $mcr->parta($n, @intervals);

Generate all partitions of n with allowed intervals p1, p2, ... pn.

Example:

    $got = $mcr->parta(4, 1,2); # [1,1,1,1],[1,1,2],[2,2]

partam

  $partitions = $mcr->partam($n, $m, @intervals);

Generate all partitions of n with m parts from the intervals p1, p2, ... pn.

Example:

  $got = $mcr->partam(4, 2, 2); # [2,2]

partm

  $partitions = $mcr->partm($n, $m);

Generate all partitions of n into m parts.

Example:

  $got = $mcr->partm(4, 2); # [1,3],[2,2]

permi

  $permutations = $mcr->permi(\@parts);

Return all permutations of the given parts list as an array-reference of array-references.

(For an efficient iterator, check out the Algorithm::Combinatorics module.)

Example:

  my $parts = [qw(1 0 1)];
  my $got = $mcr->permi($parts);
  # [1,0,1],[1,1,0],[0,1,1],[0,1,1],[1,1,0],[1,0,1]

pfold

  $sequences = $mcr->pfold($n, $m, $f);

Generate "paper folding" sequences, where n is the number of terms to calculate, m is the size of the binary representation of the folding function, and f is the folding function number, which can range from 0 to 2^m - 1.

To quote the book, "Put a rectangular strip of paper on a flat surface in front of you, with the long dimension going left to right. Now pick up the right end of the paper and fold it over onto the left end. Repeat this process a few times and unfold the paper. [There will be] a sequence of creases in the paper, some will look like valleys and some will look like ridges... Let valley creases be symbolized by the number 1 and ridge creases by the number 0..."

Example:

  # "regular paper folding sequence"
  # "folding in the same direction all the time"
  $got = $mcr->pfold(1, 1, 1); # [1]
  $got = $mcr->pfold(2, 1, 1); # [1,1]
  $got = $mcr->pfold(3, 1, 1); # [1,1,0]

  # but other parameters can generate more interesting rhythms...
  $got = $mcr->pfold(15, 4, 0); # [0,0,1,0,0,1,1,0,0,0,1,1,0,1,1]
  $got = $mcr->pfold(15, 4, 1); # [1,0,0,0,1,1,0,0,1,0,0,1,1,1,0]

reverse_at

  $sequence = $mcr->reverse_at($n, $parts);

Reverse a section of a parts sequence at n.

Examples:

  $parts = [qw(1 0 1 0 0)];
  $got = $mcr->reverse_at(0, $parts); # [0,0,1,0,1]
  $got = $mcr->reverse_at(1, $parts); # [1,0,0,1,0]
  $got = $mcr->reverse_at(2, $parts); # [1,0,0,0,1]
  $got = $mcr->reverse_at(3, $parts); # [1,0,1,0,0]

rotate_n

  $sequence = $mcr->rotate_n($n, $parts);

Rotate a necklace of the given parts, n times.

Examples:

  $parts = [qw(1 0 1 0 0)];
  $got = $mcr->rotate_n(0, $parts); # [1,0,1,0,0]
  $got = $mcr->rotate_n(1, $parts); # [0,1,0,1,0]
  $got = $mcr->rotate_n(2, $parts); # [0,0,1,0,1]
  $got = $mcr->rotate_n(3, $parts); # [1,0,0,1,0]
  $got = $mcr->rotate_n(4, $parts); # [0,1,0,0,1]
  $got = $mcr->rotate_n(5, $parts); # [1,0,1,0,0]

SEE ALSO

https://abrazol.com/books/rhythm1/ - "Creating Rhythms", the book.

https://ology.github.io/2023/03/02/creating-rhythms-with-perl/ - my write-up.

The t/01-methods.t and eg/* programs included with this distribution.

Algorithm::Combinatorics

Data::Munge

Integer::Partition

List::Util

Math::Sequence::DeBruijn

Moo

Music::AtonalUtil

Music::CreatingRhythms::SqrtContinued

AUTHOR

Gene Boggs <gene@cpan.org>

COPYRIGHT AND LICENSE

This software is Copyright (c) 2023 by Gene Boggs.

This is free software, licensed under:

  The Artistic License 2.0 (GPL Compatible)