-
Notifications
You must be signed in to change notification settings - Fork 5
/
quantum
72 lines (59 loc) · 1.85 KB
/
quantum
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
#!/usr/bin/env perl
use strict;
use warnings;
use Data::Dumper::Compact qw(ddc);
use MIDI::Util qw(setup_score set_chan_patch midi_format);
use Music::Scales qw(get_scale_notes);
use Quantum::Superpositions::Lazy;
my $max = shift || 16;
my $bpm = shift || 100;
my $scale_note = shift || 'D';
my $treble_scale_name = shift || 'dorian';
my $bass_scale_name = shift || 'pminor';
my $treble_patch = shift || 4;
my $bass_patch = shift || 35;
my $treble_octave = 5;
my $bass_octave = 3;
my $channel = 0;
my @treble_notes = map { $_ . $treble_octave } get_scale_notes($scale_note, $treble_scale_name);
my @bass_notes = map { $_ . $bass_octave } get_scale_notes($scale_note, $bass_scale_name);
my @phrases;
for my $n (1 .. $max) {
my ($realized, @phrase);
while (!@phrase || ($phrase[0] eq $phrase[1] || $phrase[0] eq $phrase[2] || $phrase[1] eq $phrase[2])) {
my @chord = map { superpos(@treble_notes) } 1 .. 3;
my @bass = map { superpos(@bass_notes) } 1 .. 4;
my $phrase = join ' ', @chord, @bass;
my $random = superpos($phrase);
$realized = $random->collapse;
@phrase = split / /, $realized;
warn ddc(\@phrase);
}
print "Phrase: $realized\n";
push @phrases, \@phrase;
}
my (@treble, @bass);
for my $p (@phrases) {
push @treble, [ @$p[0 .. 2] ];
push @bass, [ @$p[3 .. 6] ];
}
my $score = setup_score(bpm => $bpm);
$score->synch(
\&bass,
\&treble,
);
$score->write_score("$0.mid");
sub bass {
set_chan_patch($score, $channel++, $bass_patch);
for my $notes (@bass) {
for my $note (midi_format(@$notes)) {
$score->n('qn', $note);
}
}
}
sub treble {
set_chan_patch($score, $channel++, $treble_patch);
for my $notes (@treble) {
$score->n('wn', midi_format(@$notes));
}
}