forked from ology/Music
-
Notifications
You must be signed in to change notification settings - Fork 0
/
primes-layered
92 lines (69 loc) · 1.68 KB
/
primes-layered
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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
#!/usr/bin/env perl
use strict;
use warnings;
###
#
# Play the prime numbers modulo the number of notes of the given scale
# in 2 parts: Fast (top) and Long (bottom)
#
# Example:
# perl primes-layered 2048 major 300 0 73; timidity primes.mid
#
# * This tiny program uses global variables. Run if that frightens you.
#
###
use Math::Prime::XS qw(primes);
use lib map { "$ENV{HOME}/sandbox/$_/lib" } qw(MIDI-Util);
use MIDI::Util qw(setup_score set_chan_patch);
use Music::Scales qw(get_scale_MIDI);
my $limit = shift || 1024;
my $scale = shift || 'major';
my $bpm = shift || 100;
my $tpatch = shift // 4;
my $bpatch = shift // 95;
my $toctave = shift || 5;
my $boctave = shift || 3;
my @primes = primes($limit);
my $score = setup_score(bpm => $bpm);
my @phrases = (
\&top,
\&bottom,
);
$score->synch(@phrases);
$score->write_score("$0.mid");
sub top {
print "top()\n";
set_chan_patch($score, 0, $tpatch);
my @scale = (
get_scale_MIDI('C', $toctave, $scale),
get_scale_MIDI('C', $toctave + 1, $scale),
);
prime_loop(\@scale);
}
sub bottom {
print "bottom()\n";
set_chan_patch($score, 1, $bpatch);
my @scale = get_scale_MIDI('C', $boctave, $scale);
prime_loop(\@scale, 'bottom');
}
sub prime_loop {
my ($scale, $flag) = @_;
my @loop;
my $duration;
if ($flag) {
@loop = @primes[0 .. @primes / 8];
$duration = 'wn';
}
else {
@loop = @primes;
$duration = 'en';
}
my $i = 0;
for my $p (@loop) {
$i++;
my $mod = $p % @$scale;
my $note = $scale->[$mod];
print "$i. P: $p, Mod: $mod, Note: $note\n";
$score->n($duration, $note);
}
}