NAME

Music::BachChoralHarmony - Parse the UCI Bach choral harmony data set

VERSION

version 0.0403

SYNOPSIS

use Music::BachChoralHarmony;

my $bach = Music::BachChoralHarmony->new;
my $songs = $bach->parse;

# show all the song ids:
print Dumper [ sort keys %$songs ];
print Dumper [ sort keys %{ $bach->data } ]; # Same

# show all the song titles:
print Dumper [ map { $songs->{$_}{title} } sort keys %$songs ];

$songs = $bach->search( id => '000106b_' );
$songs = $bach->search( id => '000106b_ 000206b_' );
$songs = $bach->search( key => 'C_M' );         # In C major
$songs = $bach->search( key => 'C_M C_m' );     # In C major or C minor
$songs = $bach->search( bass => 'C' );          # With a C note in the bass
$songs = $bach->search( bass => 'C D' );        # With C or D in the bass
$songs = $bach->search( bass => 'C & D' );      # With C and D in the bass
$songs = $bach->search( chord => 'C_M' );       # With a C major chord
$songs = $bach->search( chord => 'C_M D_m' );   # With a C major or a D minor chord
$songs = $bach->search( chord => 'C_M & D_m' ); # With C major and D minor chords
$songs = $bach->search( notes => 'C E G' );     # With the notes C or E or G
$songs = $bach->search( notes => 'C & E & G' ); # With C and E and G
# Args can be combined too:
$songs = $bach->search( key => 'C_M C_m', chord => 'X_m & F_M' );

# Possibly handy:
my $notes = $bach->bits2notes('100000000000');     # [ C ]
$notes = $bach->bits2notes('010000000000');        # [ Db ]
$notes = $bach->bits2notes('000000000010');        # [ Bb ]
$notes = $bach->bits2notes( '000000000010', '#' ); # [ A# ]
$notes = $bach->bits2notes('110000000010');        # [ C Db Bb ]

DESCRIPTION

Music::BachChoralHarmony parses the UCI Bach choral harmony data set of 60 chorales.

This module does a few simple things:

* It turns the UCI CSV data into a perl data structure.

* It combines the Bach BWV number, song title and key with the data.

* It converts the UCI YES/NO note specification into a bit string and named note list.

* It allows searching by ids, keys, notes, and chords.

The BWV and titles were collected from an Internet Archive and filled-in from https://bach-chorales.com/. The keys were computed with a music21 program, and if missing filled-in again from https://bach-chorales.com/. Check out the links in the "SEE ALSO" section for more information.

ATTRIBUTES

data_file

$file = $bach->data_file;

The local file where the Bach choral harmony data set resides.

Default: dist_dir()/jsbach_chorals_harmony.data

key_title

$file = $bach->key_title;

The local file where the key signatures and titles for each song are listed by BWV number.

Default: dist_dir()/jsbach_BWV_keys_titles.txt

data

$songs = $bach->data;

The data resulting from the "parse" method.

METHODS

new

$bach = Music::BachChoralHarmony->new();

Create a new Music::BachChoralHarmony object.

parse

$songs = $bach->parse();

Parse the data_file and key_title files into a data hash reference of each song keyed by the song id. Each song includes a BWV identifier, title, key and list of events. The event list is made of hash references with a notes bit-string, bass note, the accent value and the resonating chord.

$songs = $bach->search( $k => $v ); # As in the SYNOPSIS above

Search the parsed result data by song ids, keys, bass notes, chords, or individual notes and return a hash reference of the format:

{ $song_id => $song_data, ... }

The id, and key can be searched by single or multiple values returning all songs that match. Note names must be separated with a space character.

The bass, chord, and notes can be searched either as or (separating note names with a space character), or as inclusive and (separating note names with an & character).

bits2notes

$notes = $bach->bits2notes($string);
$notes = $bach->bits2notes( $string, $accidental );

Convert a bit-string of 12 binary positions to a note list array reference.

The accidental can be given as # sharp or b flat in the case of enharmonic notes. Default: b

The dataset notes bit-string is defined by position as follows:

0  => C
1  => C# or Db
2  => D
3  => D# or Eb
4  => E
5  => F
6  => F# or Gb
7  => G
8  => G# or Ab
9  => A
10 => A# or Bb
11 => B

So if a C note is present in the current phrase, the first bit will be set to 1, otherwise 0. If a Bb note is present, the penultimate bit will be set, etc.

SEE ALSO

The eg/* and t/01-methods.t files in this distribution.

Moo

Text::CSV

File::ShareDir

List::Util

https://archive.ics.uci.edu/ml/datasets/Bach+Choral+Harmony is the dataset itself.

https://web.archive.org/web/20140515065053/http://www.jsbchorales.net/bwv.shtml was the original site.

http://www.bach-chorales.com/BachChorales.htm is a more modern site.

https://github.com/ology/Bach-Chorales/ is a web app that displays chord transitions with this module.

https://github.com/ology/Bach-Chorales/blob/master/bin/key.py is a program written to extract the key signature.

https://github.com/ology/Bach-Chorales/blob/master/chorales.zip are the collected MIDI files and PDF transcriptions.

THANK YOU

Dan Book (DBOOK) for the ShareDir clues.

AUTHOR

Gene Boggs <gene@cpan.org>

COPYRIGHT AND LICENSE

This software is copyright (c) 2019 by Gene Boggs.

This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.