musicality 0.11.1 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (124) hide show
  1. checksums.yaml +5 -5
  2. data/.coveralls.yml +1 -0
  3. data/.ruby-version +1 -1
  4. data/.travis.yml +4 -0
  5. data/ChangeLog.md +11 -0
  6. data/README.md +3 -0
  7. data/Rakefile +11 -3
  8. data/lib/musicality/composition/model/rhythm.rb +33 -0
  9. data/lib/musicality/composition/model/rhythm_class.rb +30 -0
  10. data/lib/musicality/composition/sequencing/drum_machine/drum_kit.rb +18 -0
  11. data/lib/musicality/composition/sequencing/drum_machine/drum_machine.rb +59 -0
  12. data/lib/musicality/composition/sequencing/drum_machine/drum_parts.rb +21 -0
  13. data/lib/musicality/composition/sequencing/drum_machine/drum_pattern.rb +66 -0
  14. data/lib/musicality/composition/sequencing/drum_machine/drum_patterns/pop_drum_patterns.rb +146 -0
  15. data/lib/musicality/composition/sequencing/note_array.rb +33 -0
  16. data/lib/musicality/composition/sequencing/note_fifo.rb +73 -0
  17. data/lib/musicality/composition/sequencing/sequenceable.rb +9 -0
  18. data/lib/musicality/composition/sequencing/sequencer.rb +35 -0
  19. data/lib/musicality/errors.rb +2 -2
  20. data/lib/musicality/notation/model/dynamics.rb +2 -2
  21. data/lib/musicality/notation/model/key.rb +42 -91
  22. data/lib/musicality/notation/model/keys.rb +35 -34
  23. data/lib/musicality/notation/model/note.rb +31 -9
  24. data/lib/musicality/notation/model/pitch.rb +2 -2
  25. data/lib/musicality/notation/parsing/convenience_methods.rb +23 -12
  26. data/lib/musicality/notation/parsing/duration_parsing.rb +3 -3
  27. data/lib/musicality/notation/parsing/key_parsing.rb +150 -0
  28. data/lib/musicality/notation/parsing/key_parsing.treetop +37 -0
  29. data/lib/musicality/notation/parsing/meter_parsing.rb +3 -3
  30. data/lib/musicality/notation/parsing/numbers/nonnegative_float_parsing.rb +3 -1
  31. data/lib/musicality/notation/parsing/numbers/nonnegative_integer_parsing.rb +1 -0
  32. data/lib/musicality/notation/parsing/numbers/nonnegative_rational_parsing.rb +1 -1
  33. data/lib/musicality/notation/parsing/numbers/positive_float_parsing.rb +4 -1
  34. data/lib/musicality/notation/parsing/numbers/positive_rational_parsing.rb +1 -1
  35. data/lib/musicality/notation/parsing/parseable.rb +13 -17
  36. data/lib/musicality/notation/parsing/pitch_parsing.rb +7 -0
  37. data/lib/musicality/notation/parsing/segment_parsing.rb +3 -0
  38. data/lib/musicality/performance/conversion/note_sequence_extractor.rb +82 -134
  39. data/lib/musicality/performance/model/note_sequence.rb +22 -3
  40. data/lib/musicality/performance/supercollider/performer.rb +2 -2
  41. data/lib/musicality/performance/supercollider/sc_drum_kits.rb +29 -0
  42. data/lib/musicality/performance/supercollider/synthdefs/bass.rb +211 -0
  43. data/lib/musicality/performance/supercollider/synthdefs/claps.rb +80 -0
  44. data/lib/musicality/performance/supercollider/synthdefs/cymbals.rb +57 -0
  45. data/lib/musicality/performance/supercollider/synthdefs/hihats.rb +67 -0
  46. data/lib/musicality/performance/supercollider/synthdefs/kicks.rb +158 -0
  47. data/lib/musicality/performance/supercollider/synthdefs/mario.rb +49 -0
  48. data/lib/musicality/performance/supercollider/{synthdefs.rb → synthdefs/other.rb} +0 -767
  49. data/lib/musicality/performance/supercollider/synthdefs/pianos.rb +46 -0
  50. data/lib/musicality/performance/supercollider/synthdefs/snares.rb +169 -0
  51. data/lib/musicality/performance/supercollider/synthdefs/toms.rb +25 -0
  52. data/lib/musicality/performance/supercollider/synthdefs/volume.rb +20 -0
  53. data/lib/musicality/pitch_class.rb +1 -1
  54. data/lib/musicality/pitch_classes.rb +3 -5
  55. data/lib/musicality/version.rb +1 -1
  56. data/lib/musicality.rb +25 -1
  57. data/musicality.gemspec +3 -2
  58. data/spec/composition/convenience_methods_spec.rb +8 -8
  59. data/spec/composition/generation/random_rhythm_generator_spec.rb +5 -5
  60. data/spec/composition/model/pitch_class_spec.rb +22 -16
  61. data/spec/composition/model/pitch_classes_spec.rb +5 -5
  62. data/spec/composition/model/rhythm_class_spec.rb +42 -0
  63. data/spec/composition/model/rhythm_spec.rb +43 -0
  64. data/spec/composition/model/scale_class_spec.rb +26 -26
  65. data/spec/composition/model/scale_spec.rb +38 -38
  66. data/spec/composition/sequencing/drum_machine/drum_machine_spec.rb +67 -0
  67. data/spec/composition/sequencing/drum_machine/drum_pattern_spec.rb +58 -0
  68. data/spec/composition/sequencing/note_array_spec.rb +94 -0
  69. data/spec/composition/sequencing/note_fifo_spec.rb +183 -0
  70. data/spec/composition/sequencing/sequencer_spec.rb +76 -0
  71. data/spec/composition/util/adding_sequence_spec.rb +33 -33
  72. data/spec/composition/util/compound_sequence_spec.rb +6 -6
  73. data/spec/composition/util/note_generation_spec.rb +34 -34
  74. data/spec/composition/util/probabilities_spec.rb +7 -7
  75. data/spec/composition/util/random_sampler_spec.rb +3 -3
  76. data/spec/composition/util/repeating_sequence_spec.rb +28 -28
  77. data/spec/musicality_spec.rb +1 -1
  78. data/spec/notation/conversion/change_conversion_spec.rb +87 -87
  79. data/spec/notation/conversion/note_time_converter_spec.rb +22 -22
  80. data/spec/notation/conversion/score_conversion_spec.rb +1 -1
  81. data/spec/notation/conversion/score_converter_spec.rb +31 -31
  82. data/spec/notation/conversion/tempo_conversion_spec.rb +11 -11
  83. data/spec/notation/model/change_spec.rb +80 -80
  84. data/spec/notation/model/key_spec.rb +135 -69
  85. data/spec/notation/model/link_spec.rb +27 -27
  86. data/spec/notation/model/meter_spec.rb +28 -28
  87. data/spec/notation/model/note_spec.rb +68 -47
  88. data/spec/notation/model/part_spec.rb +19 -19
  89. data/spec/notation/model/pitch_spec.rb +69 -68
  90. data/spec/notation/model/score_spec.rb +50 -47
  91. data/spec/notation/parsing/articulation_parsing_spec.rb +4 -4
  92. data/spec/notation/parsing/convenience_methods_spec.rb +49 -10
  93. data/spec/notation/parsing/duration_nodes_spec.rb +13 -13
  94. data/spec/notation/parsing/duration_parsing_spec.rb +10 -10
  95. data/spec/notation/parsing/key_parsing_spec.rb +19 -0
  96. data/spec/notation/parsing/link_nodes_spec.rb +7 -7
  97. data/spec/notation/parsing/link_parsing_spec.rb +4 -4
  98. data/spec/notation/parsing/meter_parsing_spec.rb +5 -5
  99. data/spec/notation/parsing/note_node_spec.rb +19 -19
  100. data/spec/notation/parsing/note_parsing_spec.rb +4 -4
  101. data/spec/notation/parsing/numbers/nonnegative_float_spec.rb +8 -8
  102. data/spec/notation/parsing/numbers/nonnegative_integer_spec.rb +2 -2
  103. data/spec/notation/parsing/numbers/nonnegative_rational_spec.rb +1 -1
  104. data/spec/notation/parsing/numbers/positive_float_spec.rb +8 -8
  105. data/spec/notation/parsing/numbers/positive_integer_spec.rb +6 -6
  106. data/spec/notation/parsing/numbers/positive_rational_spec.rb +6 -6
  107. data/spec/notation/parsing/pitch_node_spec.rb +7 -7
  108. data/spec/notation/parsing/pitch_parsing_spec.rb +2 -2
  109. data/spec/notation/parsing/segment_parsing_spec.rb +3 -3
  110. data/spec/notation/util/function_spec.rb +15 -15
  111. data/spec/notation/util/transition_spec.rb +12 -12
  112. data/spec/notation/util/value_computer_spec.rb +35 -36
  113. data/spec/performance/conversion/glissando_converter_spec.rb +24 -24
  114. data/spec/performance/conversion/note_sequence_extractor_spec.rb +39 -39
  115. data/spec/performance/conversion/portamento_converter_spec.rb +23 -23
  116. data/spec/performance/midi/midi_util_spec.rb +41 -41
  117. data/spec/performance/midi/part_sequencer_spec.rb +10 -10
  118. data/spec/performance/midi/score_sequencer_spec.rb +15 -15
  119. data/spec/performance/midi/score_sequencing_spec.rb +2 -2
  120. data/spec/performance/util/optimization_spec.rb +9 -9
  121. data/spec/printing/note_engraving_spec.rb +16 -16
  122. data/spec/printing/score_engraver_spec.rb +5 -5
  123. data/spec/spec_helper.rb +5 -0
  124. metadata +85 -30
@@ -0,0 +1,46 @@
1
+ module Musicality
2
+ module SuperCollider
3
+ module SynthDefs
4
+
5
+ CHEAP_PIANO = SynthDef.new(name: "cheappiano", params: { :out => 0, :freq => 440, :amp => 1, :dur => 1, :gate => 1, :pan => 0 },
6
+ body: <<-SCLANG,
7
+ var sig, in, n = 6, max = 0.04, min = 0.01, delay, pitch, detune, hammer;
8
+ freq = freq.cpsmidi;
9
+ hammer = Decay2.ar(Impulse.ar(0.001), 0.008, 0.04, LFNoise2.ar([2000,4000].asSpec.map(amp), 0.25));
10
+ sig = Mix.ar(Array.fill(3, { arg i;
11
+ detune = #[-0.04, 0, 0.03].at(i);
12
+ delay = (1/(freq + detune).midicps);
13
+ CombL.ar(hammer, delay, delay, 50 * amp)
14
+ }) );
15
+
16
+ sig = HPF.ar(sig,50) * EnvGen.ar(Env.perc(0.0001,dur, amp * 4, -1), gate: gate, doneAction:2);
17
+ Out.ar(out, Pan2.ar(sig, pan));
18
+ SCLANG
19
+ credit: "based on something posted 2008-06-17 by jeff, based on an old example by james mcc",
20
+ source: "https://github.com/supercollider-quarks/SynthDefPool",
21
+ )
22
+
23
+ EVERYTHING_RHODES = SynthDef.new(name: "everythingrhodes", params: { :out => 0, :freq => 440, :amp => 0.1, :gate => 1,
24
+ :lforate => 1.85, :lfowidth => 0.5, :cutoff => 2000, :rq => 0.2, :pan => 0.0 },
25
+ body: <<-SCLANG,
26
+ var pulse, filter, env;
27
+
28
+ pulse = Pulse.ar(freq*[1,33.5.midiratio],[0.2,0.1],[0.7,0.3]);
29
+ env = EnvGen.ar(Env.adsr(0.0,1.0,0.8,3.0),gate,doneAction:2);
30
+ //keyboard tracking filter cutoff
31
+ filter = BLowPass4.ar(pulse,(cutoff*(env.squared))+200+freq,rq);
32
+
33
+ Out.ar(out,Pan2.ar(Mix(filter)*env*amp,pan));
34
+ SCLANG
35
+ credit: <<-EOS,
36
+ Sound recipes from:
37
+ Mitchell Sigman (2011) Steal this Sound. Milwaukee, WI: Hal Leonard Books
38
+ adapted for SuperCollider and elaborated by Nick Collins (http://www.sussex.ac.uk/Users/nc81/index.html)
39
+ under GNU GPL 3 as per SuperCollider license
40
+ EOS
41
+ source: "https://github.com/acarabott/roundhouse-synth-design-course-2014",
42
+ )
43
+
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,169 @@
1
+ module Musicality
2
+ module SuperCollider
3
+ module SynthDefs
4
+
5
+ SNARE1 = SynthDef.new(name: "snare1", params: { :out => 0, :amp => 0.8 },
6
+ body: <<-SCLANG,
7
+ var env0, env1, env2, env1m, oscs, noise, sig;
8
+
9
+ env0 = EnvGen.ar(Env([0.5, 1, 0.5, 0], [0.005, 0.03, 0.10], [-4, -2, -4]));
10
+ env1 = EnvGen.ar(Env([110, 60, 49], [0.005, 0.1], [-4, -5]));
11
+ env1m = env1.midicps;
12
+ env2 = EnvGen.ar(Env([1, 0.4, 0], [0.05, 0.13], [-2, -2]), doneAction:2);
13
+
14
+ oscs = LFPulse.ar(env1m, 0, 0.5, 1, -0.5) +
15
+ LFPulse.ar(env1m * 1.6, 0, 0.5, 0.5, -0.25);
16
+ oscs = LPF.ar(oscs, env1m * 1.2, env0);
17
+ oscs = oscs + SinOsc.ar(env1m, 0.8, env0);
18
+
19
+ noise = WhiteNoise.ar(0.2);
20
+ noise = HPF.ar(noise, 200, 2);
21
+ noise = BPF.ar(noise, 6900, 0.6, 3) + noise;
22
+ noise = noise * env2;
23
+
24
+ sig = oscs + noise;
25
+ sig = sig.clip2(1) * amp;
26
+
27
+ Out.ar(out, sig.dup);
28
+ SCLANG
29
+ source: "https://github.com/acarabott/roundhouse-synth-design-course-2014",
30
+ )
31
+
32
+ SNARE2 = SynthDef.new(name: "snare2", params: { :sfreq => 1500, :out => 0 },
33
+ body: <<-SCLANG,
34
+ var tri = Mix([LFTri.ar([111, 175, 224])]) * 0.5;
35
+ var sine = Mix([SinOsc.ar([330, 180])]) * 0.5;
36
+ var env = EnvGen.ar(Env.perc(0.01, 0.2), doneAction:2);
37
+ var snares = WhiteNoise.ar(1);
38
+ var snareEnv = EnvGen.ar(Env.perc(0.01, 0.2));
39
+
40
+ snares = HPF.ar(snares, sfreq);
41
+ snares = snares * snareEnv;
42
+
43
+ Out.ar(out, Mix([tri, sine, snares]) * env);
44
+ SCLANG
45
+ credit: "Based on Sound on Sound Synth Secrets 35, by Arthur Carabott",
46
+ source: "https://github.com/acarabott/roundhouse-synth-design-course-2014",
47
+ )
48
+
49
+ SOS_SNARE = SynthDef.new(name: "SOSsnare", params: { :out => 0, :decay => 0.12, :drum_mode_level => 0.25, :snare_level => 40, :snare_tightness => 3000, :freq => 405, :amp => 0.8 },
50
+ body: <<-SCLANG,
51
+ var drum_mode_sin_1, drum_mode_sin_2, drum_mode_pmosc, drum_mode_mix,
52
+ drum_mode_env;
53
+ var snare_noise, snare_brf_1, snare_brf_2, snare_brf_3, snare_brf_4,
54
+ snare_reson;
55
+ var snare_env;
56
+ var snare_drum_mix;
57
+
58
+ drum_mode_env = EnvGen.ar(Env.perc(0.005, decay), 1.0, doneAction: 2);
59
+ drum_mode_sin_1 = SinOsc.ar(freq*0.53, 0, drum_mode_env * 0.5);
60
+ drum_mode_sin_2 = SinOsc.ar(freq, 0, drum_mode_env * 0.5);
61
+ drum_mode_pmosc = PMOsc.ar( Saw.ar(freq*0.85), 184, 0.5/1.3, mul: drum_mode_env*5, add: 0);
62
+ drum_mode_mix = Mix.new([drum_mode_sin_1, drum_mode_sin_2, drum_mode_pmosc]) * drum_mode_level;
63
+
64
+ // choose either noise source below
65
+ // snare_noise = Crackle.ar(2.01, 1);
66
+ snare_noise = LFNoise0.ar(20000, 0.1);
67
+ snare_env = EnvGen.ar(Env.perc(0.005, decay, curve:-5), 1.0, doneAction: 2);
68
+ snare_brf_1 = BRF.ar(in: snare_noise, freq: 8000, mul: 0.5, rq: 0.1);
69
+ snare_brf_2 = BRF.ar(in: snare_brf_1, freq: 5000, mul: 0.5, rq: 0.1);
70
+ snare_brf_3 = BRF.ar(in: snare_brf_2, freq: 3600, mul: 0.5, rq: 0.1);
71
+ snare_brf_4 = BRF.ar(in: snare_brf_3, freq: 2000, mul: snare_env, rq: 0.0001);
72
+ snare_reson = Resonz.ar(snare_brf_4, snare_tightness, mul: snare_level) ;
73
+ snare_drum_mix = Mix.new([drum_mode_mix, snare_reson]) * 5 * amp;
74
+ Out.ar(out, [snare_drum_mix, snare_drum_mix])
75
+ SCLANG
76
+ credit: "recipe basically from Gordon Reid
77
+ http://www.soundonsound.com/sos/Mar02/articles/synthsecrets0302.asp
78
+ programmed by Renick Bell, renick_at_gmail.com",
79
+ source: "https://github.com/willieavendano/SC-SynthDefs/blob/master/DrumMachines",
80
+ )
81
+
82
+ SNARE_OTO_309 = SynthDef.new(name: "snare_oto309", params: { :out => 0, :amp => 0.1, :pan => 0 },
83
+ body: <<-SCLANG,
84
+ var env0, env1, env2, env1m, oscs, noise, son;
85
+
86
+ env0 = EnvGen.ar(Env.new([0.5, 1, 0.5, 0], [0.005, 0.03, 0.10], [-4, -2, -4]));
87
+ env1 = EnvGen.ar(Env.new([110, 60, 49], [0.005, 0.1], [-4, -5]));
88
+ env1m = env1.midicps;
89
+ env2 = EnvGen.ar(Env.new([1, 0.4, 0], [0.05, 0.13], [-2, -2]), doneAction:2);
90
+
91
+ oscs = LFPulse.ar(env1m, 0, 0.5, 1, -0.5) + LFPulse.ar(env1m * 1.6, 0, 0.5, 0.5, -0.25);
92
+ oscs = LPF.ar(oscs, env1m*1.2, env0);
93
+ oscs = oscs + SinOsc.ar(env1m, 0.8, env0);
94
+
95
+ noise = WhiteNoise.ar(0.2);
96
+ noise = HPF.ar(noise, 200, 2);
97
+ noise = BPF.ar(noise, 6900, 0.6, 3) + noise;
98
+ noise = noise * env2;
99
+
100
+ son = oscs + noise;
101
+ son = son.clip2(1) * amp;
102
+
103
+ Out.ar(out, Pan2.ar(son, pan));
104
+ SCLANG
105
+ credit: "from 08091500Acid309 by_otophilia",
106
+ source: "https://github.com/supercollider-quarks/SynthDefPool",
107
+ )
108
+
109
+ SNARE_STEIN = SynthDef.new(name: "snare_stein", params: { :out => 0, :amp => 0.1, :pan => 0 },
110
+ body: <<-SCLANG,
111
+ var snare, filtWhite;
112
+
113
+ filtWhite = LPF.ar(WhiteNoise.ar(1), 7040, 1);
114
+
115
+ snare = (SinOsc.ar(330,0,0.25) * EnvGen.ar(Env.perc(0.0005,0.055))) + (SinOsc.ar(185,0,0.25) * EnvGen.ar(Env.perc(0.0005,0.075))) + (filtWhite * EnvGen.ar(Env.perc(0.0005,0.2), doneAction: 2) * 0.2) + (HPF.ar(filtWhite, 523, 1) * EnvGen.ar(Env.perc(0.0005,0.183)) * 0.2);
116
+ Out.ar(out, Pan2.ar(snare * amp * 10, pan));
117
+ SCLANG
118
+ credit: "Snare written by Esben Stein, I believe",
119
+ source: "https://github.com/supercollider-quarks/SynthDefPool",
120
+ )
121
+
122
+ SNARE3 = SynthDef.new(name: "snare", params: { :amp => 1, :dur => 0.05, :out => 0 },
123
+ body: <<-SCLANG,
124
+ dur = dur * 16;
125
+ Out.ar(out, amp * XLine.ar(2,1/1000,dur) * BPF.ar(PinkNoise.ar(0.8), XLine.ar(20000,1000,dur, doneAction:2), 0.8).dup);
126
+ SCLANG
127
+ source: "https://github.com/bwestergard/supercollider-experiments",
128
+ )
129
+
130
+ SNARE_909 = SynthDef.new(name: "snare909", params: { :out => 0, :lpFreq => 1000, :vol => 1, :gate => 1 },
131
+ body: <<-SCLANG,
132
+ var sig1, sig2;
133
+ var triEnv;
134
+ var shifted1;
135
+ var shifted2;
136
+ var sinEnv;
137
+ var sin1, sin2;
138
+ var mixed;
139
+ var sig3;
140
+ var noiseEnv;
141
+
142
+ // tri -> final mixer
143
+ triEnv = Env.adsr(0, 0.4, 0, 0, curve: -4, peakLevel: 0.5);
144
+ sig1 = LFTri.ar(111, 0, 0.5) * EnvGen.kr(triEnv, gate: gate, doneAction: 2);
145
+ shifted1 = FreqShift.ar(sig1, 175);
146
+ shifted2 = FreqShift.ar(sig1, 224);
147
+ sig1 = Mix.new([shifted1, shifted2]);
148
+
149
+ // sines -> final mixer
150
+ sin1 = SinOsc.ar(330, mul: 0.2);
151
+ sin2 = SinOsc.ar(180, mul: 0.2);
152
+ sinEnv = Env.adsr(0, 0.2, 0, 0);
153
+ sig2 = Mix.new([sin1, sin2]) * EnvGen.kr(sinEnv, gate: gate, doneAction: 2);
154
+
155
+ // noise -> final mixer
156
+ noiseEnv = Env.adsr(0, 0.3, 0, 0);
157
+ sig3 = LPF.ar(WhiteNoise.ar() * EnvGen.kr(noiseEnv, gate: gate, doneAction: 2), 1000);
158
+ sig3 = HPF.ar(sig3, 600);
159
+
160
+ mixed = Mix.new([sig1, sig2, sig3]);
161
+ mixed = LPF.ar(mixed, lpFreq) * vol;
162
+ Out.ar(out, mixed ! 2);
163
+ SCLANG
164
+ source: "https://github.com/mattvears/supercollider-stuff",
165
+ )
166
+
167
+ end
168
+ end
169
+ end
@@ -0,0 +1,25 @@
1
+ module Musicality
2
+ module SuperCollider
3
+ module SynthDefs
4
+
5
+ TOM1 = SynthDef.new(name: "tom1", params: { :out => 0, :freq => 200, :amp => 1, :pan => 0.0 },
6
+ body: <<-SCLANG,
7
+ var env, tom;
8
+ env = EnvGen.kr(Env.perc(0.001, 0.1, 1, -5), 1, doneAction:2);
9
+ tom = SinOsc.ar(freq) * env;
10
+ Out.ar(out, Pan2.ar(tom, pan, amp));
11
+ SCLANG
12
+ source: "http://superdupercollider.blogspot.com/2009/02/simple-drum-machine.html"
13
+ )
14
+
15
+ FM_TOM = SynthDef.new(name: "fmtom", params: { :out => 0, :freq => 200, :gate => 1, :amp => 1 },
16
+ body: <<-SCLANG,
17
+ var tom = PMOsc.ar(freq, 280, Line.kr(0.0, 12, 1), mul: EnvGen.ar(Env.adsr(0.003,0.2,0,0), gate, levelScale: 0.3, doneAction: 2));
18
+ Out.ar(out, tom * amp ! 2);
19
+ SCLANG
20
+ source: "https://github.com/mattvears/supercollider-stuff",
21
+ )
22
+
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,20 @@
1
+ module Musicality
2
+ module SuperCollider
3
+ module SynthDefs
4
+
5
+ VOLUME_CONTROL = SynthDef.new(name: "volume_control", params: { :in => nil, :out => nil, :control => nil },
6
+ body: <<-SCLANG,
7
+ var sig = In.ar([in,in+1]) * In.kr(control);
8
+ Out.ar(out,sig);
9
+ SCLANG
10
+ credit: "James Tunnell",
11
+ )
12
+
13
+ VOLUME_CHANGE = SynthDef.new(name: "volume_change", params: { :vol_bus => nil, :vol => nil, :dur => nil },
14
+ body: " Out.kr(vol_bus, Line.kr(In.kr(vol_bus), vol, dur));",
15
+ credit: "James Tunnell",
16
+ )
17
+
18
+ end
19
+ end
20
+ end
@@ -20,7 +20,7 @@ end
20
20
 
21
21
  end
22
22
 
23
- class Fixnum
23
+ class Integer
24
24
  def to_pc
25
25
  PitchClass.from_i self
26
26
  end
@@ -1,6 +1,6 @@
1
1
  module Musicality
2
2
 
3
- module PitchClasses
3
+ module PitchClasses
4
4
  C = Bs = 0
5
5
  Cs = Db = 1
6
6
  D = 2
@@ -15,8 +15,6 @@ module PitchClasses
15
15
  B = Cb = 11
16
16
  end
17
17
 
18
- PITCH_CLASSES = PitchClasses.constants.map do |sym|
19
- PitchClasses.const_get(sym)
20
- end.sort
18
+ PITCH_CLASSES = PitchClasses.constants.map { |sym| PitchClasses.const_get(sym) }.sort
21
19
 
22
- end
20
+ end
@@ -1,3 +1,3 @@
1
1
  module Musicality
2
- VERSION = "0.11.1"
2
+ VERSION = "0.12.0"
3
3
  end
data/lib/musicality.rb CHANGED
@@ -38,6 +38,7 @@ require 'musicality/notation/parsing/numbers/nonnegative_float_parsing'
38
38
  require 'musicality/notation/parsing/numbers/nonnegative_rational_parsing'
39
39
  require 'musicality/notation/parsing/pitch_parsing'
40
40
  require 'musicality/notation/parsing/pitch_node'
41
+ require 'musicality/notation/parsing/key_parsing'
41
42
  require 'musicality/notation/parsing/duration_parsing'
42
43
  require 'musicality/notation/parsing/duration_nodes'
43
44
  require 'musicality/notation/parsing/articulation_parsing'
@@ -78,6 +79,18 @@ require 'musicality/composition/util/note_generation'
78
79
  require 'musicality/composition/model/scale'
79
80
  require 'musicality/composition/model/scale_class'
80
81
  require 'musicality/composition/model/scale_classes'
82
+ require 'musicality/composition/model/rhythm_class'
83
+ require 'musicality/composition/model/rhythm'
84
+
85
+ require 'musicality/composition/sequencing/sequenceable'
86
+ require 'musicality/composition/sequencing/note_fifo'
87
+ require 'musicality/composition/sequencing/sequencer'
88
+ require 'musicality/composition/sequencing/note_array'
89
+ require 'musicality/composition/sequencing/drum_machine/drum_parts'
90
+ require 'musicality/composition/sequencing/drum_machine/drum_pattern'
91
+ require 'musicality/composition/sequencing/drum_machine/drum_patterns/pop_drum_patterns'
92
+ require 'musicality/composition/sequencing/drum_machine/drum_kit'
93
+ require 'musicality/composition/sequencing/drum_machine/drum_machine'
81
94
 
82
95
  require 'musicality/composition/generation/counterpoint_generator'
83
96
  require 'musicality/composition/generation/random_rhythm_generator'
@@ -121,10 +134,21 @@ require 'musicality/performance/supercollider/node'
121
134
  require 'musicality/performance/supercollider/synth'
122
135
  require 'musicality/performance/supercollider/group'
123
136
  require 'musicality/performance/supercollider/synthdef'
124
- require 'musicality/performance/supercollider/synthdefs'
137
+ require 'musicality/performance/supercollider/synthdefs/bass'
138
+ require 'musicality/performance/supercollider/synthdefs/claps'
139
+ require 'musicality/performance/supercollider/synthdefs/cymbals'
140
+ require 'musicality/performance/supercollider/synthdefs/hihats'
141
+ require 'musicality/performance/supercollider/synthdefs/kicks'
142
+ require 'musicality/performance/supercollider/synthdefs/mario'
143
+ require 'musicality/performance/supercollider/synthdefs/other'
144
+ require 'musicality/performance/supercollider/synthdefs/pianos'
145
+ require 'musicality/performance/supercollider/synthdefs/snares'
146
+ require 'musicality/performance/supercollider/synthdefs/toms'
147
+ require 'musicality/performance/supercollider/synthdefs/volume'
125
148
  require 'musicality/performance/supercollider/performer'
126
149
  require 'musicality/performance/supercollider/conductor'
127
150
  require 'musicality/performance/supercollider/score_conducting'
151
+ require 'musicality/performance/supercollider/sc_drum_kits'
128
152
 
129
153
  #
130
154
  # Printing
data/musicality.gemspec CHANGED
@@ -22,10 +22,11 @@ SuperCollider."
22
22
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
23
23
  spec.require_paths = ["lib"]
24
24
 
25
- spec.add_development_dependency "bundler", "~> 1.7"
25
+ spec.add_development_dependency "bundler", "~> 2.0"
26
26
  spec.add_development_dependency "rake", "~> 10.0"
27
- spec.add_development_dependency "rspec", "~> 2.9"
27
+ spec.add_development_dependency "rspec", "~> 3.5"
28
28
  spec.add_development_dependency "pry"
29
+ spec.add_development_dependency "coveralls", '~> 0.8'
29
30
 
30
31
  spec.add_dependency "treetop", "~> 1.5"
31
32
  spec.add_dependency 'midilib', '~> 2.0'
@@ -5,12 +5,12 @@ describe 'transpose' do
5
5
  notes = "/4A2,C2 /4D2,F2,Gb2 /8 /8E4".to_notes
6
6
  semitones = 3
7
7
  notes2 = transpose(notes,semitones)
8
-
9
- notes2.size.should eq(notes.size)
8
+
9
+ expect(notes2.size).to eq(notes.size)
10
10
  notes2.each_index do |i|
11
11
  notes2[i].pitches.each_with_index do |pitch2,j|
12
12
  pitch = notes[i].pitches[j]
13
- pitch2.diff(pitch).should eq(semitones)
13
+ expect(pitch2.diff(pitch)).to eq(semitones)
14
14
  end
15
15
  end
16
16
  end
@@ -30,19 +30,19 @@ end
30
30
  describe method do
31
31
  context 'given no args' do
32
32
  it 'should produce an empty array' do
33
- send(method).should eq([])
33
+ expect(send(method)).to eq([])
34
34
  end
35
35
  end
36
36
 
37
37
  context 'given one pitch' do
38
38
  it 'should produce an array with one note, with proper duration' do
39
- send(method,*[C2]).should eq([Note.new(dur,C2)])
39
+ expect(send(method,*[C2])).to eq([Note.new(dur,C2)])
40
40
  end
41
41
  end
42
42
 
43
43
  context 'given one pitch group' do
44
44
  it 'should produce an array with one note, given pitch group, and with proper duration' do
45
- send(method,*[[C2,E2,G2]]).should eq([Note.new(dur,[C2,E2,G2])])
45
+ expect(send(method,*[[C2,E2,G2]])).to eq([Note.new(dur,[C2,E2,G2])])
46
46
  end
47
47
  end
48
48
 
@@ -51,10 +51,10 @@ end
51
51
  pg1 = A3
52
52
  pg2 = [B3,G3]
53
53
  pg3 = F4
54
- send(method,*[pg1,pg2,pg3]).should eq([
54
+ expect(send(method,*[pg1,pg2,pg3])).to eq([
55
55
  Note.new(dur,pg1), Note.new(dur,pg2), Note.new(dur,pg3)
56
56
  ])
57
57
  end
58
58
  end
59
59
  end
60
- end
60
+ end
@@ -13,27 +13,27 @@ describe RandomRhythmGenerator do
13
13
  end
14
14
  end
15
15
  end
16
-
16
+
17
17
  before :all do
18
18
  @rrgs = [
19
19
  { 1/8.to_r => 0.25, 1/4.to_r => 0.5, 1/2.to_r => 0.25 },
20
20
  { 1/6.to_r => 0.25, 1/4.to_r => 0.25, 1/3.to_r => 0.25, 1/12.to_r => 0.25 }
21
21
  ].map {|durs_w_probs| RandomRhythmGenerator.new(durs_w_probs) }
22
22
  end
23
-
23
+
24
24
  describe '#random_rhythm' do
25
25
  it 'should return durations that add to given total dur' do
26
26
  @rrgs.each do |rrg|
27
27
  [3,1,1/2.to_r,5/8.to_r,15/16.to_r].each do |total_dur|
28
28
  20.times do
29
29
  rhythm = rrg.random_rhythm(total_dur)
30
- rhythm.inject(0,:+).should eq(total_dur)
30
+ expect(rhythm.inject(0,:+)).to eq(total_dur)
31
31
  end
32
32
  end
33
33
  end
34
34
  end
35
35
  end
36
-
36
+
37
37
  describe '#random_dur' do
38
38
  it 'should return a random duration, according to the probabilities given at initialization' do
39
39
  @rrgs.each do |rrg|
@@ -42,7 +42,7 @@ describe RandomRhythmGenerator do
42
42
  rrg.durations.each_with_index do |dur,i|
43
43
  count = counts[dur]
44
44
  tgt_prob = rrg.probabilities[i]
45
- (count / 1000.to_f).should be_within(0.05).of(tgt_prob)
45
+ expect((count / 1000.to_f)).to be_within(0.05).of(tgt_prob)
46
46
  end
47
47
  end
48
48
  end
@@ -4,48 +4,54 @@ include PitchClasses
4
4
 
5
5
  describe PitchClass do
6
6
  it 'should define the MOD constant' do
7
- PitchClass.constants.should include(:MOD)
7
+ expect(PitchClass.constants).to include(:MOD)
8
8
  end
9
-
9
+
10
10
  describe '.from_i' do
11
11
  it 'should return the given integer % PitchClass::MOD' do
12
- PitchClass.from_i(-1).should eq(11)
13
- PitchClass.from_i(12).should eq(0)
14
- PitchClass.from_i(2).should eq(2)
15
- PitchClass.from_i(16).should eq(4)
12
+ expect(PitchClass.from_i(-1)).to eq(11)
13
+ expect(PitchClass.from_i(12)).to eq(0)
14
+ expect(PitchClass.from_i(2)).to eq(2)
15
+ expect(PitchClass.from_i(16)).to eq(4)
16
16
  end
17
17
  end
18
18
 
19
- it 'should add the #to_pc method to the Fixnum class' do
20
- 5.methods.should include(:to_pc)
19
+ it 'should add the #to_pc method to the Integer class' do
20
+ expect(5.methods).to include(:to_pc)
21
21
  end
22
22
 
23
23
  it 'should add the #to_pc method to the Pitch class' do
24
- Pitch.new.methods.should include(:to_pc)
24
+ expect(Pitch.new.methods).to include(:to_pc)
25
25
  end
26
26
 
27
27
  it 'should add the #to_pcs method to Enumerable classes, like Array' do
28
- [1,2,3].methods.should include(:to_pcs)
28
+ expect([1,2,3].methods).to include(:to_pcs)
29
29
  end
30
-
30
+
31
31
  describe 'Pitch#to_pc' do
32
32
  it 'should send semitone through PitchClass.from_i' do
33
33
  [ C4, D3, E5, G5,
34
34
  Pitch.new(semitone: 4),
35
35
  Pitch.new(semitone: 13),
36
36
  ].each do |pitch|
37
- pitch.to_pc.should eq(PitchClass.from_i(pitch.semitone))
37
+ expect(pitch.to_pc).to eq(PitchClass.from_i(pitch.semitone))
38
38
  end
39
39
  end
40
40
  end
41
41
 
42
- describe 'Fixnum#to_pc' do
42
+ describe 'Integer#to_pc' do
43
43
  it 'should pass self to PitchClass.from_i' do
44
44
  [-1,12,2,16].each do |i|
45
- i.to_pc.should eq(PitchClass.from_i(i))
45
+ expect(i.to_pc).to eq(PitchClass.from_i(i))
46
46
  end
47
47
  end
48
48
  end
49
+
50
+ describe 'Integer#to_pcs' do
51
+ it 'should pass self to PitchClass.from_i' do
52
+ expect([-1,12,2,16].to_pcs).to eq([-1.to_pc,12.to_pc,2.to_pc,16.to_pc])
53
+ end
54
+ end
49
55
 
50
56
  describe '.invert' do
51
57
  before :all do
@@ -62,13 +68,13 @@ describe PitchClass do
62
68
 
63
69
  it 'should produce a pitch class' do
64
70
  @cases.each do |input_pc, output_pc|
65
- PitchClass.invert(input_pc).should eq(output_pc)
71
+ expect(PitchClass.invert(input_pc)).to eq(output_pc)
66
72
  end
67
73
  end
68
74
 
69
75
  it 'should produce a pitch class that when inverted again produces the original pitch class' do
70
76
  @cases.each do |input_pc, output_pc|
71
- PitchClass.invert(output_pc).should eq(input_pc)
77
+ expect(PitchClass.invert(output_pc)).to eq(input_pc)
72
78
  end
73
79
  end
74
80
  end
@@ -5,7 +5,7 @@ pc_syms = [:C, :Db, :D, :Eb, :E, :F, :Gb, :G, :Ab, :A, :Bb, :B]
5
5
  describe PitchClasses do
6
6
  it 'should include pitch-class constants for C, Db, D, ...' do
7
7
  pc_syms.each do |sym|
8
- PitchClasses.constants.should include(sym)
8
+ expect(PitchClasses.constants).to include(sym)
9
9
  end
10
10
  end
11
11
  end
@@ -13,12 +13,12 @@ end
13
13
 
14
14
  describe 'PITCH_CLASSES' do
15
15
  it 'should be in the Musicality module namespace' do
16
- Musicality.constants.should include(:PITCH_CLASSES)
16
+ expect(Musicality.constants).to include(:PITCH_CLASSES)
17
17
  end
18
-
18
+
19
19
  it 'should have each constant value in PitchClasses' do
20
20
  PitchClasses.constants.each do |sym|
21
- PITCH_CLASSES.should include(PitchClasses.const_get(sym))
21
+ expect(PITCH_CLASSES).to include(PitchClasses.const_get(sym))
22
22
  end
23
23
  end
24
- end
24
+ end
@@ -0,0 +1,42 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
2
+
3
+ describe RhythmClass do
4
+ describe '.new' do
5
+ it 'should raise ArgumentError if given portions contains any zero(s)' do
6
+ expect { RhythmClass.new([1,0,2]) }.to raise_error(ArgumentError)
7
+ end
8
+ end
9
+
10
+ describe '#portions' do
11
+ it 'should return the same portions given initially' do
12
+ portions = [4,2,-2,-1]
13
+ rc = RhythmClass.new(portions)
14
+ expect(rc.portions).to eq(portions)
15
+ end
16
+ end
17
+
18
+ describe '#portions_sum' do
19
+ it 'should return the sum of portions using their absolute value' do
20
+ rc = RhythmClass.new([4,2,-2,-1])
21
+ expect(rc.portions_sum).to eq(9)
22
+ end
23
+ end
24
+
25
+ describe '#to_rhythm' do
26
+ it 'should produce the expected Rhythm object' do
27
+ portions = [5,1,-7,3,-1,2]
28
+ rhythm_class = RhythmClass.new(portions)
29
+ portions_sum = rhythm_class.portions_sum
30
+ rhythm_duration = 2
31
+ rhythm = rhythm_class.to_rhythm(rhythm_duration)
32
+
33
+ expect(rhythm).to be_a(Rhythm)
34
+ expect(rhythm.durations.size).to eq(portions.size)
35
+ portions.each_with_index do |portion, idx|
36
+ dur = rhythm.durations[idx]
37
+ expect(dur).to eq(rhythm_duration * Rational(portion, portions_sum))
38
+ end
39
+ expect(rhythm.durations_sum).to eq(rhythm_duration)
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,43 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
2
+
3
+ describe Rhythm do
4
+ describe '.new' do
5
+ it 'should raise ArgumentError if given durations contains any zero(s)' do
6
+ expect { Rhythm.new([1,0,2]) }.to raise_error(ArgumentError)
7
+ end
8
+ end
9
+
10
+ describe '#durations' do
11
+ it 'should return the same portions given initially' do
12
+ durations = [4,2,-2,-1]
13
+ rc = Rhythm.new(durations)
14
+ expect(rc.durations).to eq(durations)
15
+ end
16
+ end
17
+
18
+ describe '#durations_sum' do
19
+ it 'should return the sum of durations using their absolute value' do
20
+ rc = Rhythm.new([4,2,-2,-1])
21
+ expect(rc.durations_sum).to eq(9)
22
+ end
23
+ end
24
+
25
+ describe '#to_notes' do
26
+ it 'should produce the expected Note objects' do
27
+ durations = [Rational(1,2), Rational(2,1), Rational(2,3)]
28
+ rhythm = Rhythm.new(durations)
29
+ durations_sum = rhythm.durations_sum
30
+ pitch = Pitches::C4
31
+ notes = rhythm.to_notes(pitch)
32
+
33
+ expect(notes.size).to eq(durations.size)
34
+ notes.each do |note|
35
+ expect(note).to be_a(Note)
36
+ end
37
+ durations.each_with_index do |dur, idx|
38
+ dur2 = notes[idx].duration
39
+ expect(dur).to eq(dur2)
40
+ end
41
+ end
42
+ end
43
+ end