rubySC 0.6.0 → 0.8.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.
- checksums.yaml +4 -4
- data/.gitignore +1 -1
- data/Gemfile +1 -1
- data/README.md +74 -31
- data/installation.sh +34 -0
- data/lib/init.sc +32 -6
- data/lib/main.rb +33 -0
- data/lib/qt/form.rb +124 -0
- data/lib/qt/form.ui +260 -0
- data/lib/rubySC.rb +43 -5
- data/lib/rubySC/accords.rb +0 -0
- data/lib/rubySC/forme.rb +9 -0
- data/lib/rubySC/harmonie.rb +56 -0
- data/lib/rubySC/harmonie/accords.rb +46 -0
- data/lib/rubySC/harmonie/harmonie.rb +55 -0
- data/lib/rubySC/harmonie/voiceLeading.rb +128 -0
- data/lib/rubySC/math.rb +5 -0
- data/lib/rubySC/melodie/Schenker.rb +15 -0
- data/lib/rubySC/melodie/{algos.rb → intervalles.rb} +21 -3
- data/lib/rubySC/melodie/melodie.rb +71 -106
- data/lib/rubySC/melodie/motif.rb +73 -0
- data/lib/rubySC/musique.rb +0 -40
- data/lib/rubySC/rythme.rb +82 -0
- data/lib/rubySC/version.rb +1 -1
- data/lib/rubySC/voix.rb +46 -33
- data/lib/samples/bip.wav +0 -0
- data/lib/samples/piano.wav +0 -0
- data/rubySC.gemspec +3 -0
- metadata +33 -3
data/lib/rubySC.rb
CHANGED
@@ -6,6 +6,8 @@ Dir.glob("rubySC/**/*") { |file|
|
|
6
6
|
require_relative file end
|
7
7
|
}
|
8
8
|
|
9
|
+
require 'set'
|
10
|
+
|
9
11
|
require 'active_support'
|
10
12
|
require 'singleton'
|
11
13
|
require 'osc-ruby'
|
@@ -25,7 +27,7 @@ class SC
|
|
25
27
|
cattr_reader :listeVoix, :valeurReceptrice
|
26
28
|
cattr_accessor :server, :portSuperCollider
|
27
29
|
|
28
|
-
include Singleton
|
30
|
+
#include Singleton
|
29
31
|
|
30
32
|
# ouvre le contact avec SuperCollider
|
31
33
|
|
@@ -102,6 +104,11 @@ class SC
|
|
102
104
|
self.send "Pbindef(\\#{voix}, \\#{arg}, Scale.#{value})"
|
103
105
|
when "instrument"
|
104
106
|
self.send "Pbindef(\\#{voix}, \\#{arg}, \\#{value})"
|
107
|
+
when "adsr"
|
108
|
+
self.send "Pbindef(\\#{voix}, \\atk, Pkey(\\dur)*#{value[0]})"
|
109
|
+
self.send "Pbindef(\\#{voix}, \\decay, Pkey(\\dur)*#{value[1]})"
|
110
|
+
self.send "Pbindef(\\#{voix}, \\sustain, Pkey(\\dur)*#{value[2]})"
|
111
|
+
self.send "Pbindef(\\#{voix}, \\rel, Pkey(\\dur)*#{value[3]})"
|
105
112
|
else
|
106
113
|
#self.send "Pbindef(\\#{voix}, \\#{arg}, #{value.to_s})"
|
107
114
|
end
|
@@ -116,6 +123,12 @@ class SC
|
|
116
123
|
end
|
117
124
|
end
|
118
125
|
|
126
|
+
def self.sample nomSample
|
127
|
+
|
128
|
+
tmp="samples/#{nomSample}.wav"
|
129
|
+
self.send "Buffer.read(s, \"#{tmp}\")"
|
130
|
+
|
131
|
+
end
|
119
132
|
# fonctions principales
|
120
133
|
|
121
134
|
public
|
@@ -126,10 +139,11 @@ class SC
|
|
126
139
|
|
127
140
|
if args[0]==nil then
|
128
141
|
args=@@listeVoix.keys
|
129
|
-
args.each do |voix|
|
130
|
-
self.send "Pdef(\\#{voix.to_s}).play"
|
131
|
-
end
|
132
142
|
end
|
143
|
+
args.each do |voix|
|
144
|
+
self.send "Pdef(\\#{voix.to_s}).play"
|
145
|
+
end
|
146
|
+
|
133
147
|
end
|
134
148
|
|
135
149
|
|
@@ -154,4 +168,28 @@ class SC
|
|
154
168
|
|
155
169
|
end
|
156
170
|
|
157
|
-
|
171
|
+
|
172
|
+
module Helper
|
173
|
+
## quelques helpers
|
174
|
+
|
175
|
+
def m numero=1
|
176
|
+
SC.listeVoix["melodie#{numero}"]
|
177
|
+
end
|
178
|
+
|
179
|
+
def org numero=1
|
180
|
+
SC.listeVoix["harmonisationDemelodie#{numero}"]
|
181
|
+
end
|
182
|
+
|
183
|
+
def h numero=0
|
184
|
+
SC.listeVoix["harmo#{numero}"]
|
185
|
+
end
|
186
|
+
|
187
|
+
def b
|
188
|
+
SC.listeVoix["basse"]
|
189
|
+
end
|
190
|
+
|
191
|
+
def li
|
192
|
+
SC.listeVoix
|
193
|
+
end
|
194
|
+
|
195
|
+
end
|
File without changes
|
data/lib/rubySC/forme.rb
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
module Harmonie
|
2
|
+
|
3
|
+
include Intervalles
|
4
|
+
|
5
|
+
def squeletteHarmonique mel, set=[0,2,4]
|
6
|
+
|
7
|
+
mel.map { |e|
|
8
|
+
e == set.any? ? true : false }
|
9
|
+
end
|
10
|
+
|
11
|
+
# Sert à détecter quel accord sous-tend une mélodie
|
12
|
+
# @format melodie [Melodie]
|
13
|
+
|
14
|
+
def detecterSet mel, intervalles=2
|
15
|
+
|
16
|
+
tmpUn=mel.sort.uniq.map { |e|
|
17
|
+
e%intervalles
|
18
|
+
}
|
19
|
+
tmpDeux=mel.sort.uniq.map { |e|
|
20
|
+
e/intervalles
|
21
|
+
}
|
22
|
+
n={}
|
23
|
+
tmpUn.size.times do |x|
|
24
|
+
n[tmpUn[x].to_s].nil? ? \
|
25
|
+
(n[tmpUn[x].to_s] = [] << tmpDeux[x]) :\
|
26
|
+
(n[tmpUn[x].to_s] << tmpDeux[x])
|
27
|
+
end
|
28
|
+
return n
|
29
|
+
end
|
30
|
+
|
31
|
+
def detectSymetrie mel
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
def analyse mel, grilleAnalyse=2, modulo=7
|
36
|
+
|
37
|
+
mel.each_slice(grilleAnalyse).map { |x|
|
38
|
+
(x[-1]-x[0])%7
|
39
|
+
}
|
40
|
+
|
41
|
+
end
|
42
|
+
|
43
|
+
# Je ne sais pas si cette fonction a du sens, vraiment
|
44
|
+
def analyseReduction mel, nbRecursion=mel.size-1, tmp=[]
|
45
|
+
|
46
|
+
tmp << mel
|
47
|
+
unless nbRecursion<1
|
48
|
+
analyseReduction (mel.each_cons(2).map { |x|
|
49
|
+
(x[-1]-x[0])
|
50
|
+
}), nbRecursion-=1, tmp
|
51
|
+
end
|
52
|
+
return tmp
|
53
|
+
end
|
54
|
+
|
55
|
+
|
56
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
#simplement un ensemble de voix marchant en simultanée
|
2
|
+
# mais selon une logique harmonique => une basse !
|
3
|
+
|
4
|
+
class Accords
|
5
|
+
include VoiceLeading
|
6
|
+
|
7
|
+
attr_accessor :grille
|
8
|
+
|
9
|
+
def initialize grille:, nbVoix:3, rythmeHarmonique:nil
|
10
|
+
@basse=grille
|
11
|
+
@realisation=Array.new(nbVoix) { |i| i=[] }
|
12
|
+
@rythmeHarmonique=rythmeHarmonique
|
13
|
+
self.realiserAccords
|
14
|
+
end
|
15
|
+
|
16
|
+
def play
|
17
|
+
3.times do |i|
|
18
|
+
Voix.new "harmo#{i}", {:instrument =>"default",
|
19
|
+
:degree => @realisation[i],
|
20
|
+
:dur => @rythmeHarmonique}
|
21
|
+
end
|
22
|
+
Voix.new "basse", {:instrument => "fatsaw",
|
23
|
+
:degree =>@basse,
|
24
|
+
:dur => @rythmeHarmonique}
|
25
|
+
#if jouer? ? SC.play : nil
|
26
|
+
end
|
27
|
+
|
28
|
+
|
29
|
+
private def foutreDansReal truc #bon j'en ai marre, OK ?
|
30
|
+
tmp=dispatchNotes truc
|
31
|
+
truc.size.times do |i|
|
32
|
+
@realisation[i] << truc [i]
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def realiserAccords
|
37
|
+
tmp=accordBasique @basse[0]
|
38
|
+
foutreDansReal tmp
|
39
|
+
grille=reduireGrille @basse
|
40
|
+
p grille
|
41
|
+
grille.each { |e|
|
42
|
+
tmp=incrementer tmp, e
|
43
|
+
p tmp
|
44
|
+
foutreDansReal tmp }
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module Harmonie
|
2
|
+
|
3
|
+
include Intervalles
|
4
|
+
|
5
|
+
def squeletteHarmonique mel, set=[0,2,4]
|
6
|
+
|
7
|
+
mel.map { |e|
|
8
|
+
set.any? {|x| e==x} ? true : false }
|
9
|
+
end
|
10
|
+
|
11
|
+
# Sert à détecter les notes paires dans une section de
|
12
|
+
#mélodie. Retourne la distance qui sépare ces notes
|
13
|
+
#typiquement, un accord parfait sera {"0 (ou 1)" => [0,1,2]}
|
14
|
+
# @format melodie [Melodie]
|
15
|
+
|
16
|
+
def detecterHarmonies mel, intervalles=2
|
17
|
+
|
18
|
+
tmpUn=mel.sort.uniq.map { |e|
|
19
|
+
e%intervalles
|
20
|
+
}
|
21
|
+
tmpDeux=mel.sort.uniq.map { |e|
|
22
|
+
e/intervalles
|
23
|
+
}
|
24
|
+
n={}
|
25
|
+
tmpUn.size.times do |x|
|
26
|
+
n[tmpUn[x].to_s].nil? ? \
|
27
|
+
(n[tmpUn[x].to_s] = [] << tmpDeux[x]) :\
|
28
|
+
(n[tmpUn[x].to_s] << tmpDeux[x])
|
29
|
+
end
|
30
|
+
return n
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
def analyse mel, grilleAnalyse=2, modulo=7
|
35
|
+
|
36
|
+
mel.each_slice(grilleAnalyse).map { |x|
|
37
|
+
(x[-1]-x[0])%7
|
38
|
+
}
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
# Je ne sais pas si cette fonction a du sens, vraiment
|
43
|
+
def analyseReduction mel, nbRecursion=mel.size-1, tmp=[]
|
44
|
+
|
45
|
+
tmp << mel
|
46
|
+
unless nbRecursion<1
|
47
|
+
analyseReduction (mel.each_cons(2).map { |x|
|
48
|
+
(x[-1]-x[0])
|
49
|
+
}), nbRecursion-=1, tmp
|
50
|
+
end
|
51
|
+
return tmp
|
52
|
+
end
|
53
|
+
|
54
|
+
|
55
|
+
end
|
@@ -0,0 +1,128 @@
|
|
1
|
+
require_relative '../melodie/intervalles.rb'
|
2
|
+
|
3
|
+
module VoiceLeading
|
4
|
+
include Intervalles
|
5
|
+
|
6
|
+
@@position = [[2,4], [2, 5],[3,5]]
|
7
|
+
#ALLLLLLLLLLLEZ
|
8
|
+
|
9
|
+
|
10
|
+
#DoubleArray de Hash. Selon la position (place dans l'array),
|
11
|
+
#puis selon le vecteur (de -3 a 3) on a une position et éventuellement
|
12
|
+
#un changement de basse
|
13
|
+
|
14
|
+
chgtPos = [
|
15
|
+
[[2,-1],[1,0],[0,-1],nil,[0,+1],[1,-1],[2,+0]],
|
16
|
+
[[2,-1],[2,+0],[2,+1],nil,[1,+1],[0,0],[0,+1]],
|
17
|
+
[[0,0],[0,+1],[2,-1],nil,[2,+1],[1,+0],[1,+1]]
|
18
|
+
]
|
19
|
+
|
20
|
+
@@matricePos=[]
|
21
|
+
3.times do |j|
|
22
|
+
@@matricePos[j]=
|
23
|
+
h=Hash.new
|
24
|
+
(-3..3).each do |i|
|
25
|
+
h[i]=chgtPos[j][i+3]
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
|
30
|
+
#VOICE_LEAD_POS=[[0,2,4], [0, 2, 5],[0,3,5]]
|
31
|
+
|
32
|
+
#réduit la grille d'accords autour d'une oscillation entre -3 et 3
|
33
|
+
#pour faire en tout 7 valeurs possibles, aka le nombre de notes dans la
|
34
|
+
#gamme diatonique
|
35
|
+
|
36
|
+
def reduireGrille grille, grilleAnalyse=7
|
37
|
+
minMax = grilleAnalyse/2
|
38
|
+
(intervalles grille).map { |e|
|
39
|
+
e=e%grilleAnalyse
|
40
|
+
if e > minMax
|
41
|
+
e=-(grilleAnalyse%e)
|
42
|
+
elsif e < -minMax
|
43
|
+
e=(grilleAnalyse%e).abs
|
44
|
+
else e
|
45
|
+
end
|
46
|
+
}
|
47
|
+
end
|
48
|
+
|
49
|
+
|
50
|
+
def incrementer accord, vecteurHarmonique
|
51
|
+
|
52
|
+
# binding.pry
|
53
|
+
position_basse=@@matricePos[(detectPosition accord)][vecteurHarmonique]
|
54
|
+
|
55
|
+
accordNv=[]
|
56
|
+
if position_basse.nil?
|
57
|
+
accordNv=accord
|
58
|
+
else
|
59
|
+
accordNv[0]=accord[0]+position_basse[1]
|
60
|
+
accordNv[1]=accordNv[0]+@@position[position_basse[0]][0]
|
61
|
+
accordNv[2]=accordNv[0]+@@position[position_basse[0]][1]
|
62
|
+
end
|
63
|
+
return accordNv
|
64
|
+
end
|
65
|
+
|
66
|
+
def detectPosition array
|
67
|
+
tmp=[]
|
68
|
+
tmp<< array[1]-array[0]
|
69
|
+
tmp<< array[2]-array[0]
|
70
|
+
case tmp
|
71
|
+
when [2,4]
|
72
|
+
return 0
|
73
|
+
when [2,5]
|
74
|
+
return 1
|
75
|
+
when [3,5]
|
76
|
+
return 2
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
# implémente selon le "vecteur harmonique" le passage d'un accord à un autre
|
81
|
+
|
82
|
+
# def incrementer accord, vecteurHarmonique
|
83
|
+
|
84
|
+
# plus=lambda{|x| x+1}
|
85
|
+
# moins= lambda{|x| x-1}
|
86
|
+
|
87
|
+
# case vecteurHarmonique
|
88
|
+
# when 0
|
89
|
+
# return accord
|
90
|
+
# when 1
|
91
|
+
# return accord.map! {|x| plus.call x}
|
92
|
+
# when -1
|
93
|
+
# return accord.map! {|x| moins.call x}
|
94
|
+
# when 2
|
95
|
+
# accord[0]-=1
|
96
|
+
# return accord
|
97
|
+
# when -2
|
98
|
+
# accord[-1]+=1
|
99
|
+
# return accord
|
100
|
+
# when 3
|
101
|
+
# accord[-1]+=1
|
102
|
+
# accord[-2]+=1
|
103
|
+
# return accord
|
104
|
+
# when -3
|
105
|
+
# accord[0]-=1
|
106
|
+
# accord[1]-=1
|
107
|
+
# return accord
|
108
|
+
# end
|
109
|
+
# end
|
110
|
+
|
111
|
+
|
112
|
+
def accordBasique basse, position=nbNotes=3, intervalleBase=2
|
113
|
+
|
114
|
+
tmp=[]
|
115
|
+
nbNotes.times do |x|
|
116
|
+
tmp << basse+intervalleBase*x
|
117
|
+
end
|
118
|
+
return tmp
|
119
|
+
end
|
120
|
+
|
121
|
+
def dispatchNotes accord
|
122
|
+
tmp=[]
|
123
|
+
accord.each { |e|
|
124
|
+
tmp << [e] }
|
125
|
+
return tmp
|
126
|
+
end
|
127
|
+
|
128
|
+
end
|
@@ -1,14 +1,14 @@
|
|
1
|
-
|
1
|
+
module Intervalles
|
2
|
+
|
3
|
+
def intervalles melodie
|
2
4
|
|
3
5
|
tmp=melodie.each_with_index.map{ |a, i|
|
4
6
|
if melodie[i+1]
|
5
7
|
then melodie[i+1]-a
|
6
8
|
end
|
7
9
|
}
|
8
|
-
|
9
10
|
tmp[0..-2]
|
10
11
|
|
11
|
-
|
12
12
|
end
|
13
13
|
|
14
14
|
def intervallesBoucle melodie
|
@@ -28,4 +28,22 @@ def intervallesRel melodie, note=0
|
|
28
28
|
ptDepart = melodie[note]
|
29
29
|
return melodie.map { |x|
|
30
30
|
x-= ptDepart }
|
31
|
+
end
|
32
|
+
|
33
|
+
def squeletteIntervallique melodie, gdIntervalle=5, petitInter=1
|
34
|
+
|
35
|
+
i=intervalles melodie
|
36
|
+
i.map! { |e|
|
37
|
+
if e<=petitInter
|
38
|
+
e=0
|
39
|
+
elsif
|
40
|
+
e>=gdIntervalle
|
41
|
+
e=2
|
42
|
+
else
|
43
|
+
e=1
|
44
|
+
end
|
45
|
+
}
|
46
|
+
|
47
|
+
end
|
48
|
+
|
31
49
|
end
|