- NAME
- SYNOPSIS
- DESCRIPTION
- METHODS
- bits2pcs number
- check_melody params ref, pitch_set
- circular_permute pitch_set
- complement pitch_set
- fnums
- forte_number_re
- forte2pcs forte_number
- gen_melody params ...
- half_prime_form pitch_set
- interval_class_content pitch_set
- intervals2pcs start_pitch, interval_set
- invariance_matrix pitch_set
- invert axis, pitch_set
- lastn array_ref, n
- mininterval from, to
- multiply factor, pitch_set
- new parameter_pairs ...
- nexti array ref
- normal_form pitch_set
- pcs2bits pitch_set
- pcs2forte pitch_set
- pcs2intervals pitch_set
- pcs2str pitch_set
- pitch2intervalclass pitch
- prime_form pitch_set
- reflect_pitch pitch, min, max
- retrograde pitch_set
- rotate rotate_by, pitch_set
- rotateto what, dir, pitch_set
- scale_degrees optional_integer
- set_complex pitch_set
- subsets length, pitch_set
- tcs pitch_set
- tcis pitch_set
- transpose transpose_by, pitch_set
- transpose_invert transpose_by, axis, pitch_set
- variances pitch_set1, pitch_set2
- zrelation pitch_set1, pitch_set2

- CHANGES
- BUGS
- RHYTHM
- SEE ALSO
- AUTHOR
- COPYRIGHT AND LICENSE

# NAME

Music::AtonalUtil - atonal music analysis and composition

# SYNOPSIS

```
use Music::AtonalUtil ();
my $atu = Music::AtonalUtil->new;
my $nf = $atu->normal_form([0,3,7]);
my $pf = $atu->prime_form(0, 4, 7);
...
```

Though see below for the (many) other methods.

# DESCRIPTION

This module contains a variety of routines suitable for atonal music composition and analysis (plus a bunch of other routines I could find no better home for). See the methods below, the test suite, and the `atonal-util`

command line interface (in App::MusicTools) for ideas on how to use these routines.

There may be errors due to misunderstanding of atonal theory by the autodidactic author. If in doubt, compare the results of this code with other software or documentation available. However, the "SEE ALSO" references have been consulted to varying degrees though the development of this module, and there are unit tests for a few things, so hopefully there are not too many bugs.

# METHODS

By default, a 12-tone system is assumed. Input values are (hopefully) mapped to reside inside this space where necessary. Most methods accept a pitch set (an array reference consisting of a list of pitch numbers, or just a list of such numbers), and most return array references containing the results. Some (but not much) sanity checking is done on the input, which may cause the code to **croak** if something is awry.

First create an object (via **new**) then call any other of the remaining methods below via that object. Results from the various methods should reside within the **scale_degrees**, unless the method returns something else. Integer math is (often) assumed.

**bits2pcs** *number*

Converts a number into a *pitch_set*, and returns said set as an array reference. Performs opposite role of the **pcs2bits** method. Will not consider bits beyond **scale_degrees** in the input number.

**check_melody** *params ref*, *pitch_set*

Given a melody (array reference of pitch numbers), and a set of parameters, returns false if the melody fails any of the rules present in the parameters, or true otherwise. See **gen_melody** for one method of melody generation. The return value in scalar context will be a boolean; in list context, the boolean will be followed by a rule name and then depending on the rule possible a third return value, an hash reference containing details of what failed where.

Parameters (at least one must be specified, doubtless more):

*dup_interval_limit*=>*count*-
Rejects the melody if there are a number of intervals equal to or greater than the specified

*count*. *exclude_interval*=> [*list of hashes*... ]-
Rejects the melody should it contain specified patterns of intervals. Only the magnitude of the interval is considered, and not the direction. An example, whose ending in rising fourths would be unacceptable in a strict atonal context:

`$atu->check_melody( [qw/60 64 57 59 60 57 65 64 62 67 72/], exclude_interval => [ { iset => [ 5, 5 ], }, # adjacent fourths ("cadential basses") ], );`

In addition to the

*iset*interval array reference, an*in*value can specify in how many intervals (above that of the*iset*) to search for the specified intervals. The following would look for two perfect fourths, optionally with some other interval between them:`{ iset => [ 5, 5 ], in => 3 },`

Intervals in any order may be considered by adding the

*sort*flag, and then numbering the intervals to match from low to high:`{ iset => [ 1, 2, 3 ], sort => 1 },`

*exclude_half_prime*=> [*list of hashes*... ]-
Rejects the melody should it contain notes comprising the specified so- called "half prime" form. The

*ps*value pitch set must be in**half_prime_form**. Otherwise identical to*exclude_prime*. *exclude_prime*=> [*list of hashes*... ]-
Rejects the melody should it contain notes comprising the specified prime forms. The

*ps*value pitch set must be in**prime_form**.`exclude_prime => [ { ps => [ 0, 3, 7 ], in => 4 }, # major or minor triad, any guise { ps => [ 0, 2, 5, 8 ], }, # 7th, any guise, exact { ps => [ 0, 2, 4, 6 ], in => 5 }, # whole tone formation ],`

Additionally, a

*subsets*key can be used to apply the rule to any subset prime form pitch set of the input pitch set. For example, to exclude 5 or 6 note subsets of the 7-35 pitch set:`exclude_prime => [ { in => 8, # in 8 (or 7 or 6) note groups subsets => [ 5, 6 ], ps => [ 0, 1, 3, 5, 6, 8, 10 ], # 7-35 (major/minor scale) }, ],`

This method probably should not be used for smaller subsets than five, as sets like 7-35 or larger have many subsets in the 4-x (13 prime form subsets, to be exact) or smaller range, and with the prime form conflation of multiple other "half prime" sets, well more pitches than one might expect can match the rule.

**circular_permute** *pitch_set*

Takes a pitch set (array reference to list of pitches or just a list of such), and returns an array reference of pitch set references as follows:

` $atu->circular_permute([1,2,3]); # [[1,2,3],[2,3,1],[3,1,2]]`

This is used by the **normal_form** method, internally. This permutation is identical to inversions in tonal theory, but is different from the **invert** method offered by this module. See also **rotate** to rotate a pitch set by a particular amount, or **rotateto** to search for something to rotate to.

**complement** *pitch_set*

Returns the pitches of the scale degrees not set in the passed pitch set (an array reference to list of pitches or just a list of such).

` $atu->complement([1,2,3]); # [0,4,5,6,7,8,9,10,11]`

Calling **prime_form** on the result will find the abstract complement of the original set, whatever that means.

**fnums**

Returns hash reference of which keys are Forte Numbers and values are array references to the corresponding pitch sets. This reference should perhaps not be fiddled with, unless the fiddler desires different results for the **forte2pcs** and **pcs2forte** calls.

**forte_number_re**

Returns a regular expression capable of matching a Forte Number.

**forte2pcs** *forte_number*

Given a Forte Number (such as `6-z44`

or `6-Z44`

), returns the corresponding pitch set as an array reference, or `undef`

if an unknown Forte Number is supplied.

**gen_melody** *params* ...

Generates a random 12-tone series, feeds that to **check_melody**, tries for a number of times until a suitable melody can be returned as an array reference. May throw an exception if something goes awry or the rules did not permit a melody. The 12-tone series will remain within a single register, so the generation of melodies with 9ths or 10ths is not possible via this method.

See **check_melody** for documentation on the parameters; setting these is mandatory. **gen_melody** offers one additional parameter to set the tessitura of the melody (in semitones; default is a 10th):

` $atu->gen_melody( melody_max_interval => 11, ... );`

**half_prime_form** *pitch_set*

Returns the "half prime" or "more normal" form of a pitch set; in scalar context returns an array reference to the resulting pitch set, while in list context returns an array reference and a subsequent hash reference containing a mapping of pitch set numbers to the original pitches (as also done by **normal_form**).

This form in particular can distinguish pitch sets that are `[0,3,7]`

from those that are `[0,4,7]`

which **prime_form** will conflate as `[0,3,7]`

and **normal_form** does not go far enough to compare different guises of these two different "half prime" classes. Note that some pitch sets have no "half prime form" distinct from the prime form; this distinction influences what Music::NeoRiemannianTonnetz can do with the pitch set, for example (see `eg/nrt-study-setclass`

of that module).

(The "half prime form" name is my invention; I have no idea if there is another term for this calculation extant in music theory literature.)

**interval_class_content** *pitch_set*

Given a pitch set with at least two elements, returns an array reference (and in list context also a hash reference) representing the interval-class vector information. Pitch sets with similar ic content tend to sound the same (see also **zrelation**).

This vector is also known as a pitch-class interval (PIC) vector or absolute pitch-class interval (APIC) vector:

https://en.wikipedia.org/wiki/Interval_vector

Uses include an indication of invariance under transposition; see also the **invariants** mode of `atonal-util`

of App::MusicTools for the display of invariant pitches. It also has uses in rhythmic analysis (see works by e.g. Godfried T. Toussaint).

**intervals2pcs** *start_pitch*, *interval_set*

Given a starting pitch (set to `0`

if unsure) and an interval set (a list of intervals or array reference of such), converts those intervals into a pitch set, returned as an array reference.

**invariance_matrix** *pitch_set*

Returns reference to an array of references that comprise the invariance under Transpose(N)Inversion operations on the given pitch set. Probably easier to use the **invariants** mode of `atonal-util`

of App::MusicTools, unless you know what you are doing.

**invert** *axis*, *pitch_set*

Inverts the given pitch set, within the degrees in scale. Set the *axis* to `0`

if unsure. Returns resulting pitch set as an array reference. Some examples or styles assume rotation with an axis of `6`

, for example:

https://en.wikipedia.org/wiki/Set_%28music%29#Serial

Has the "retrograde-inverse transposition" of `0 11 3`

becoming `4 8 7`

. This can be reproduced via:

```
my $p = $atu->retrograde(0,11,3);
$p = $atu->invert(6, $p);
$p = $atu->transpose(1, $p);
```

**lastn** *array_ref*, *n*

Utility method. Returns the last N elements of the supplied array reference, or the entire list if N exceeds the number of elements available. Returns nothing if the array reference is empty, but otherwise will throw an exception if something is awry.

**mininterval** *from*, *to*

Returns the minimum interval including sign between the given pitch numbers within the confines of the **scale_degrees**; that is, C to F would be five, F to C negative five, B to C one, and C to B negative one.

**multiply** *factor*, *pitch_set*

Multiplies the supplied pitch set by the given factor, modulates the results by the **scale_degrees** setting, and returns the results as an array reference.

**new** *parameter_pairs ...*

Constructor. The degrees in the scale can be adjusted via:

` Music::AtonalUtil->new(DEG_IN_SCALE => 17);`

or some other positive integer greater than one, to use a non-12-tone basis for subsequent method calls. This value can be set or inspected via the **scale_degrees** call. **Note that while non-12-tone systems are in theory supported, they have not really been tested.** Modern rhythmic analysis overlaps with some of the routines available in this code; this might be a practical use for a different number of degrees in the "scale." See "RHYTHM" for ideas.

**nexti** *array ref*

Utility method. Returns the next item from the supplied array reference. Loops around to the beginning of the list if the bounds of the array are exceeded. Caches the index for subsequent lookups. Part of the **geti**, **nexti**, **reseti**, **seti**, and **whati** set of routines, which are documented here:

**geti***array ref*-
Returns current position in array (which may be larger than the number of elements in the list, as the routines modulate the iterator down as necessary to fit the reference).

**reseti***array ref*-
Sets the iterator to zero for the given array reference.

**seti***array ref*,*index*-
Sets the iterator to the given value.

**whati***array ref*-
Returns the value of what is currently pointed at in the array reference. Does not advance the index.

**normal_form** *pitch_set*

Returns two values in list context; first, the normal form of the passed pitch set as an array reference, and secondly, a hash reference linking the normal form values to array references containing the input pitch numbers those normal form values represent. An example may clarify:

` my ($ps, $lookup) = $atu->normal_form(60, 64, 67, 72); # c' e' g' c''`

`$ps`

is`[0,4,7]`

, as`60`

and`72`

are equivalent pitches, so both get mapped to`0`

.`$lookup`

contains hash keys`0`

,`4`

, and`7`

, where`4`

points to an array reference containing`64`

,`7`

to an array reference containing`67`

, and`0`

an array reference containing both`60`

and`72`

. This allows software to answer "what original pitches of the input are X" type questions.

Use `scalar`

context or the following to select just the normal form array reference:

` my $just_the_nf_thanks = ($atu->normal_form(...))[0];`

The "packed from the right" method outlined in the www.mta.ca link ("SEE ALSO") is employed, so may return different normal forms than the Allen Forte method. There is stub code for the Allen Forte method in this module, though I lack enough information to verify if that code is correct. The Forte Numbers on Wikipedia match that of the www.mta.ca link method.

See also **normalize** of Music::NeoRiemannianTonnetz for a different take on normal and prime forms.

**pcs2bits** *pitch_set*

Converts a *pitch_set* into a **scale_degrees**-bit number.

```
7 3 0
[0,3,7] -> 000010001001 -> 137
```

These can be inspected via `printf`

, and the usual bit operations applied as desired.

```
my $mask = $atu->pcs2bits(0,3,7);
sprintf '%012b', $mask; # 000010001001
if ( $mask == ( $atu->pcs2bits($other_pset) & $mask ) ) {
# $other_pset has all the same bits on as $mask does
...
}
```

**pcs2forte** *pitch_set*

Given a pitch set, returns the Forte Number of that set. The Forte Numbers use lowercase `z`

, for example `6-z44`

. `undef`

will be returned if no Forte Number exists for the pitch set.

**pcs2intervals** *pitch_set*

Given a pitch set of at least two elements, returns the list of intervals between those pitch elements. This list is returned as an array reference.

**pcs2str** *pitch_set*

Given a pitch set (or string with commas in it) returns the pitch set as a string in `[0,1,2]`

form.

```
$atu->pcs2str([0,3,7]) # "[0,3,7]"
$atu->pcs2str(0,3,7) # "[0,3,7]"
$atu->pcs2str("0,3,7") # "[0,3,7]"
```

**pitch2intervalclass** *pitch*

Returns the interval class a given pitch belongs to (0 is 0, 11 maps down to 1, 10 down to 2, ... and 6 is 6 for the standard 12 tone system). Used internally by the **interval_class_content** method.

**prime_form** *pitch_set*

Returns the prime form of a given pitch set (via **normal_form** and various other operations on the passed pitch set) as an array reference.

See also **normalize** of Music::NeoRiemannianTonnetz for a different take on normal and prime forms.

**reflect_pitch** *pitch*, *min*, *max*

Utility method. Constrains the supplied pitch to reside within the supplied minimum and maximum limits, by "reflecting" the pitch back off the limits. For example, given the min and max limits of 6 and 12:

```
pitch ... 10 11 12 13 14 15 16 17 18 19 20 21 ...
result ... 10 11 12 11 10 9 8 7 6 7 8 9 ...
```

This may be of use in a Music::LilyPondUtil `*_pitch_hook`

function to keep the notes within a certain range (modulus math, by contrast, produces a sawtooth pattern with occasional leaps).

**retrograde** *pitch_set*

Fancy term for the `reverse`

of a list. Returns reference to array of said reversed list.

**rotate** *rotate_by*, *pitch_set*

Rotates the pitch set by the integer supplied as the first argument. Returns an array reference of the resulting pitch set. (**circular_permute** performs all the possible rotations for a pitch set.)

**rotateto** *what*, *dir*, *pitch_set*

Utility method. Rotates (via **rotate**) a given array reference to the desired element *what* (using string comparisons). Returns an array reference of the thus rotated set. Throws an exception if anything goes wrong with the input or search.

*what* is searched for from the first element and subsequent elements, assuming a positive *dir* value. Set a negative *dir* to invert the direction of the search.

**scale_degrees** *optional_integer*

Without arguments, returns the number of scale degrees (12 by default). If passed a positive integer greater than two, sets the scale degrees to that. Note that changing this will change the results from almost all the methods this module offers, and has not been tested.

**set_complex** *pitch_set*

Computes the set complex, or a 2D array with the pitch set as the column headers, pitch set inversion as the row headers, and the combination of those two for the intersection of the row and column headers. Returns reference to the resulting array of arrays.

Ideally the first pitch of the input pitch set should be 0 (so the input may need reduction to **prime_form** first).

**subsets** *length*, *pitch_set*

Returns the subsets of a given pitch set as an array of array refs. *length* should be `-1`

to select for pitch sets of one element less, or a positive value of a magnitude less than the pitch set to return the subsets of a specific magnitude.

```
$atu->subsets(-1, [0,3,7]) # different ways to say same thing
$atu->subsets( 2, [0,3,7])
```

The input set will be modulated to the **scale_degrees** limit, and any duplicate pitches excluded before the subsets are generated. The return sets might be further reduced by the caller via **half_prime_form** or **prime_form** or some other method to (sometimes) effect an even greater reduction in the number of subsets. However, by default, no such reduction is done by this method, beyond initial input set sanitization.

**tcs** *pitch_set*

Returns array reference consisting of the transposition common-tone structure (TCS) for the given pitch set, that is, for each of the possible transposition operations under the **scale_degrees** in question, how many common tones there are with the original set.

**tcis** *pitch_set*

Like **tcs**, except uses **transpose_invert** instead of just **transpose**.

**transpose** *transpose_by*, *pitch_set*

Transposes the given pitch set by the given integer value in *transpose_by*. Returns the result as an array reference.

**transpose_invert** *transpose_by*, *axis*, *pitch_set*

Performs **invert** on given pitch set (set *axis* to `0`

if unsure), then transposition as per **transpose**. Returns the result as an array reference.

**variances** *pitch_set1*, *pitch_set2*

Given two pitch sets, in scalar context returns the shared notes of those two pitch sets as an array reference. In list context, returns the shared notes (intersection), difference, and union as array references.

**zrelation** *pitch_set1*, *pitch_set2*

Given two pitch sets, returns true if the two sets share the same **interval_class_content**, false if not.

# CHANGES

Version 1.0 reordered and otherwise mucked around with calling conventions (mostly to allow either an array reference or a list of values for pitch sets), but not the return values. Except for **normal_form**, which obtained additional return values, so you can figure out which of the input pitches map to what (a feature handy for Music::NeoRiemannianTonnetz related operations, or so I hope).

Otherwise I generally try not to break the interface. Except when I do.

# BUGS

## Reporting Bugs

If the bug is in the latest version, send a report to the author. Patches that fix problems or add new features are welcome.

http://github.com/thrig/Music-AtonalUtil

## Known Issues

Poor naming conventions and vague and conflicting standards of music theory on top of any mistakes in understanding thereof by the author.

Also, it would be nice to deal with a "Pitch" object that knows how to return the pitch modulus the `scale_degrees`

via some method (but that would likely entail a Project that would unify a whole bunch of `Music::*`

modules into some grand unified PerlMusic thingy, though I am busy doing other things, so will not be writing that).

# RHYTHM

Rhythmic analysis might begin with:

` Music::AtonalUtil->new(DEG_IN_SCALE => 16);`

Assuming 16 beats in a measure, as per the Godfried Toussaint article ("SEE ALSO"), the "clave Son" rhythm that in lilypond might run something like `c8. c16 r8 c8 r8 c8 c4`

could be represented using the "onset-coordinate vector" notation of `(0,3,6,10,12)`

and perhaps passed to such routines as **interval_class_content** for subsequent analysis. For example, a measure of evenness (the sum of the interval arc-lengths) can be obtained via:

```
use Music::AtonalUtil ();
my $atu = Music::AtonalUtil->new( DEG_IN_SCALE => 16 );
my $ics = ( $atu->interval_class_content( 0, 3, 6, 10, 12 ) )[1];
my $sum = 0;
for my $k ( keys %$ics ) {
$sum += $k * $ics->{$k};
}
```

See `atonal-util`

of App::MusicTools for **beats2set** and **set2beats**, for beat pattern to "pitch" set conversions.

# SEE ALSO

Reference and learning material (mostly where I learned from):

"Computational geometric aspects of rhythm, melody, and voice-leading" by Godfried Toussaint (and other rhythm articles by the same).

Musimathics, Vol. 1, p.311-317 by Gareth Loy.

http://www.mta.ca/faculty/arts-letters/music/pc-set_project/pc-set_new/

"Serial Composition" by Smith-Brindle Reginald.

"The Structure of Atonal Music" by Allen Forte.

Additional Perl resources for music include:

Music::Chord::Positions and Music::NeoRiemannianTonnetz for other means of wrangling music.

Music::LilyPondUtil for where the pitch-number to lilypond-note-name code has been moved to (or see also Music::PitchNum), and App::MusicTools for where the command line utilities have been stashed, e.g.

`atonal-util`

.

# AUTHOR

thrig - Jeremy Mates (cpan:JMATES) `<jmates at cpan.org>`

# COPYRIGHT AND LICENSE

Copyright (C) 2012-2015 by Jeremy Mates

This module is free software; you can redistribute it and/or modify it under the Artistic License (2.0).