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.0806

SYNOPSIS

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

DESCRIPTION

Music::CreatingRhythms provides most of the 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 handy nonetheless.

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);

This method takes a set of binary sequences and converts them into intervals.

That is, it converts binary sequences of the form [[1],[1,0],[1,0,0]] into a set of intervals of the form [[1],[2],[3]].

This basically is the number of zeros following a one.

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);

This method calculates the continued fraction convergent given a set of terms. It is used to find the best rational approximations to real numbers by using their continued fraction expansions.

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.

* This method needs Math::NumSeq::SqrtContinued to be installed. YMMV

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

The comp* methods are used to generate compositions of numbers, which are ways to partition an integer into smaller parts. The arguments passed to these functions determine the specific composition that is generated.

  $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_digits

  $count = $mcr->count_digits($digit, $n);

Count the number of a given digit in a string or vector (n).

Examples:

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

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);

This method generates the largest de Bruijn sequence of order n, which is a cyclic sequence containing all possible combinations of length n with no repeating subsequences.

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

The neck* methods generate binary necklaces of a certain length with or without specific constraints on their intervals.

  $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 methods, 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

The part* methods are used to generate all possible partitions of an integer into smaller parts, either with or without specific constraints on the lengths of those parts.

  $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.

This method generates "paper folding" sequences, which are binary sequences that represent the creases on a piece of paper after it has been folded multiple times in different directions. The arguments passed to this function determine the specific sequence that is generated.

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

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)