### ----------------------------------------------------
### -- Music::Helpers
### -- Licenses: Artistic
### -- Authors: Pepe Schwarz <peschwa@gmail.com>
### -- File: README.md
### ----------------------------------------------------
NAME
====

Music::Helpers - Abstractions for handling musical content

SYNOPSIS
========

    use Music::Helpers;

    my $mode = Mode.new(:root(C), :mode('major'))

    # prints 'C4 E4 G4 ==> C maj (inversion: 0)'
    say $mode.tonic.Str;

    # prints 'F4 A4 C5 ==> F maj (inversion: 0)'
    say $mode.next-chord($mode.tonic, intervals => [P4]).Str;

DESCRIPTION
===========

This module provides a few OO abstraction for handling musical content. Explicitly these are the classes `Mode`, `Chord` and `Note` as well as Enums `NoteName` and `Interval`. As anyone with even passing musical knowledge knows, `Mode`s and `Chord`s consists of `Note`s with one of those being the root and the others having a specific half-step distance from this root. As the main purpose for this module is utilizing these classes over MIDI (via [Audio::PortMIDI](https://github.com/jonathanstowe/Audio-PortMIDI/)), non-standard tunings will have to be handled by the instruments that play these notes. For convenience two enums, `NoteName` and `Interval` are exported as well. Note that the former uses only sharp notes, and uses a lower case 's' as the symbol for that, e.g:

    say Cs; # works
    say C#, Db, C♯, D♭; # don't work

`Interval` only exports from unison to octave:

    # prints (P1 => 0 m2 => 1 M2 => 2 m3 => 3 M3 => 4 P4 => 5 TT => 6 P5 => 7 m6 => 8 M6 => 9 m7 => 10 M7 => 11 P8 => 12)
    say Interval.enums.sort(*.value);

The arithmetic operators `&infix:<+>` and `&infix:<->` are overloaded and exported for any combination between `Note`s and `Interval`s, and return new `Note`s or `Interval`s, depending on invocation:

    my $c = Note.new(:48midi);
    # $g contains 'Note.new(:43midi)'
    my $g = ($c - P4);
    # prints 'P4'
    say $c - $g;

A `Mode` knows, which natural triads it contains, and memoizes the `Note`s and `Chord`s on each step of the scale for probably more octaves than necessary. (That is, 10 octaves, from C-1 to C9, MIDI values 0 to 120.) Further, a `Chord` knows via a set of Roles applied at construction time, which kind of alterations on it are feasible. E.g:

    my $mode  = Mode.new(:root(F), :mode<major>);
    my $fmaj  = $mode.tonic;
    my $fdom7 = $fmaj.dom7;
    # prints 'F4 G4 C5 => F4 sus2 (inversion: 0)'
    say $fsus2.Str;

    my $mode = Mode.new(:root(F), :mode<minor>);
    my $fmin = $mode.tonic;
    # dies, "Method 'dom7' not found for invocant of class 'Music::Helpers::Chord+{Music::Helpers::min}'
    my $fdom7 = $fmin.dom7;

Although I do readily admit that not all possible alterations and augmentations are currently implemented. A `Chord` tells you, which variants it support via the methods `.variant-methods` and `.variant-roles`:

    my @notes = do [ Note.new(midi => $_ + 4 * P8) for C, E, G];
    my $chord = Chord.new(:@notes, :0inversion);

    # prints '[(sus2) (sus4) (maj6) (maj7) (dom7)]'
    say $chord.variant-roles;

    # prints '[sus2 sus4 maj6 maj7 dom7]'
    say $chord.variant-methods;

    # prints 'C4 E4 G4 B4 ==> C4 maj7 (inversion: 0)'
    say $chord.variant-methods[3]($chord);

Note that `.variant-methods` is usually what you want to use when trying to create a variant of a given `Chord`.

Further, positive and negative inversions are supported via the method `.invert`:

    # prints 'C5 F5 A5 ==> F5 maj (inversion: 2)'
    say $fmaj.invert(2).Str;

    # prints 'C4 F4 A4 ==> F4 maj (inversion: 2)'
    say $fmaj.invert(-1).Str;

Finally, a `Note` knows how to build a `Audio::PortMIDI::Event` that can be sent via a `Audio::PortMIDI::Stream`, and a `Chord` knows to ask the `Note`s it consists of for these Events:

    # prints a whole lot, not replicated for brevity
    say $fmaj.OnEvents;

Note that this documentation is a work in progress. The file bin/example.pl6 in this repository might be of interest.


