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
@@ -1,112 +1,106 @@
|
|
1
|
+
require_relative 'intervalles.rb'
|
2
|
+
require_relative 'motif.rb'
|
3
|
+
|
1
4
|
class Melodie
|
2
5
|
|
3
|
-
|
6
|
+
include Intervalles
|
7
|
+
include Motif
|
8
|
+
|
9
|
+
attr_reader :dessinRythmique, :dessinMelodique, :analyse
|
4
10
|
|
5
11
|
def initialize
|
6
|
-
|
7
|
-
@dessinRythmique = creerRythme @dessinMelodique
|
12
|
+
|
8
13
|
@@nbMel=0
|
14
|
+
@analyse={}
|
15
|
+
|
16
|
+
@dessinMelodique = creerMelodie
|
17
|
+
self.analyser
|
18
|
+
@dessinRythmique = self.creerRythme
|
19
|
+
|
9
20
|
end
|
10
|
-
|
11
|
-
def mettreVoix instrument="default"
|
12
|
-
@@nbMel+=1
|
13
|
-
Voix.new "melodie#{@@nbMel}",
|
14
|
-
({:instrument => instrument,
|
15
|
-
:degree => @dessinMelodique,
|
16
|
-
:dur => @dessinRythmique})
|
17
21
|
|
18
|
-
end
|
19
22
|
|
23
|
+
def enclencher instrument="default"
|
24
|
+
p "instrument sera #{instrument}"
|
25
|
+
@@nbMel+=1
|
26
|
+
Voix.new "melodie#{@@nbMel}",
|
27
|
+
({:instrument => instrument,
|
28
|
+
:degree => @dessinMelodique,
|
29
|
+
:dur => @dessinRythmique})
|
20
30
|
end
|
21
31
|
|
32
|
+
def analyser
|
22
33
|
|
23
|
-
|
34
|
+
@analyse["motifs"]=squeletteMotivique @dessinMelodique
|
35
|
+
@analyse["intervalles"]=squeletteIntervallique @dessinMelodique
|
36
|
+
|
37
|
+
end
|
24
38
|
|
25
|
-
|
26
|
-
|
39
|
+
|
40
|
+
|
41
|
+
def creerRythme options={:intervalles=>1, :motifs=>1}
|
42
|
+
|
43
|
+
tmp=[]
|
44
|
+
l=lambda {|x|
|
45
|
+
unless options[x].nil?
|
46
|
+
tmp<<@analyse[x.to_s].map(&options[x].method(:*))
|
47
|
+
end}
|
48
|
+
|
49
|
+
options.each { |k,v|
|
50
|
+
l.call k }
|
51
|
+
|
52
|
+
result=[]
|
53
|
+
(@dessinMelodique.size-1).times do |i|
|
54
|
+
result << tmp.map{ |row| row[i] }.reduce(&:+)
|
27
55
|
end
|
28
|
-
end
|
29
56
|
|
30
|
-
|
31
|
-
melodie.map { |e| e+= deCombien }
|
32
|
-
end
|
57
|
+
return result
|
33
58
|
|
34
|
-
|
59
|
+
end
|
35
60
|
|
36
|
-
|
37
|
-
tmpDeux=melUn.map {|x|
|
38
|
-
if x == melDeux[i] then i +=1 ; true
|
39
|
-
else false
|
40
|
-
end
|
41
|
-
}
|
42
|
-
p tmpDeux
|
61
|
+
def vitesse
|
43
62
|
|
44
|
-
if tmpDeux.count(true) == melDeux.size
|
45
|
-
then tmpDeux
|
46
|
-
else nil end
|
47
63
|
end
|
48
64
|
|
49
|
-
#grand moment de désarroi algorithmique
|
50
65
|
|
51
|
-
#
|
66
|
+
#quelques raccourcis
|
52
67
|
|
68
|
+
def inter
|
69
|
+
intervalles @dessinMelodique
|
70
|
+
end
|
53
71
|
|
54
|
-
|
55
|
-
|
72
|
+
def interAbs
|
73
|
+
intervallesAbs @dessinMelodique
|
74
|
+
end
|
56
75
|
|
57
|
-
|
76
|
+
def interRel note=0
|
77
|
+
intervallesMel @dessinMelodique, note
|
78
|
+
end
|
58
79
|
|
59
|
-
# notePrincipale
|
60
|
-
# noteSecondaire
|
61
|
-
# noteOrnementale
|
62
80
|
|
81
|
+
def detectDoublons
|
82
|
+
@dessinMelodique.map.with_index(1) { |e, i|
|
83
|
+
unless i==@dessinMelodique.size
|
84
|
+
@dessinMelodique[i] - @dessinMelodique[i-1] == 0 ? true : false
|
85
|
+
end }[0..-2]
|
86
|
+
end
|
63
87
|
|
64
|
-
# UnVersUn = lambda { noteOrnementale+=1}
|
65
|
-
# UnVersDeux = lambda { |a| orner squeletteRythmique(a.index-noteOrnementale) }
|
66
|
-
# UnVersTrois
|
67
|
-
# DeuxversUn
|
68
|
-
# DeuxVersDeux
|
69
|
-
# DeuxVersTrois
|
70
|
-
# TroisVersUn
|
71
|
-
# TRoisVersDeux
|
72
|
-
# TroisVErsTRois
|
73
88
|
|
74
|
-
|
75
|
-
|
76
|
-
# when 1
|
77
|
-
# case a
|
78
|
-
# when 1
|
79
|
-
# UnVersUn.call
|
80
|
-
# when 2
|
81
|
-
# UnVersDeux.call
|
82
|
-
# when 3
|
83
|
-
# UnVersTrois.call
|
84
|
-
# end
|
85
|
-
# when 2
|
86
|
-
# case a
|
87
|
-
# when 1
|
88
|
-
# DeuxVersUn.call
|
89
|
-
# when 2
|
90
|
-
# DeuxVersDeux.call
|
91
|
-
# when 3
|
92
|
-
# DeuxVersTrois.call
|
93
|
-
# end
|
94
|
-
# when 3
|
95
|
-
# case a
|
96
|
-
# when 1
|
97
|
-
# TroisVersUn.call
|
98
|
-
# when 2
|
99
|
-
# TroisVersDeux.call
|
100
|
-
# when 3
|
101
|
-
# TroisVersTrois.call
|
102
|
-
# end
|
89
|
+
end
|
90
|
+
|
103
91
|
|
104
92
|
|
93
|
+
def creerMelodie nbNote=rand(10..30)
|
105
94
|
|
106
|
-
|
95
|
+
Array.new (nbNote) do |note|
|
96
|
+
note=[0,0,1,1,2,3,3,3,3,4,4,4,4,5,6].sample #manière un peu bourrine de "pondérer" les notes possibles
|
97
|
+
end
|
98
|
+
end
|
107
99
|
|
100
|
+
def transpose melodie, deCombien
|
101
|
+
melodie.map { |e| e+= deCombien }
|
102
|
+
end
|
108
103
|
|
109
|
-
# end
|
110
104
|
|
111
105
|
def rejoindre noteDepart, noteArrivee, nbTemps
|
112
106
|
|
@@ -146,32 +140,3 @@ trille = lambda { tmp= [note-1, note, note+1, note] }
|
|
146
140
|
end
|
147
141
|
|
148
142
|
end
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
#analyse rythmique basique
|
153
|
-
# si intervalle grand => pt d'appui
|
154
|
-
# si note conjointes et/ou similaire => plus rapide
|
155
|
-
#pour l'instant, pas de note d'approche
|
156
|
-
|
157
|
-
|
158
|
-
def creerRythme melodie=nil #analyse
|
159
|
-
|
160
|
-
if melodie.nil?
|
161
|
-
return RubySC_CONST::Rythmes.sample
|
162
|
-
end
|
163
|
-
|
164
|
-
rythme = intervallesMel melodie
|
165
|
-
rythme.map! { |inter|
|
166
|
-
case inter.abs
|
167
|
-
when 1
|
168
|
-
note = 1
|
169
|
-
|
170
|
-
else
|
171
|
-
note=2
|
172
|
-
end
|
173
|
-
}
|
174
|
-
rythme << 4
|
175
|
-
|
176
|
-
end
|
177
|
-
|
@@ -0,0 +1,73 @@
|
|
1
|
+
module Motif
|
2
|
+
|
3
|
+
def detectPattern melodie, filtreLongueur=3
|
4
|
+
|
5
|
+
|
6
|
+
mel=(convertirABC melodie).join
|
7
|
+
|
8
|
+
|
9
|
+
siz = mel.length
|
10
|
+
tmp = []
|
11
|
+
|
12
|
+
(0..siz-1).each do |n|
|
13
|
+
(n..siz-1).each do |i|
|
14
|
+
tmp << mel[n..i]
|
15
|
+
end
|
16
|
+
end
|
17
|
+
tmp.to_set
|
18
|
+
|
19
|
+
result=Hash.new
|
20
|
+
tmp.each_with_index { |e, i|
|
21
|
+
result[tmp[i]]=(mel.scan /#{tmp[i]}/).size
|
22
|
+
}
|
23
|
+
|
24
|
+
|
25
|
+
return result.select { |k,v| k.size>=filtreLongueur and v > 1}
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
def convertirABC melodie, setChiffres=['c','d','e','f','g','a','b','c']
|
30
|
+
|
31
|
+
toutDansOctave melodie
|
32
|
+
return melodie.map { |e|
|
33
|
+
e= setChiffres[e]
|
34
|
+
}
|
35
|
+
end
|
36
|
+
|
37
|
+
def squeletteMotivique melodie
|
38
|
+
|
39
|
+
mel=(convertirABC melodie).join
|
40
|
+
patterns=detectPattern melodie, 1
|
41
|
+
|
42
|
+
#on met en exergue les plus longs patterns qui se répètent
|
43
|
+
patterns=patterns.keys.group_by(&:size).reverse_each { |k,v|
|
44
|
+
v.each {|i|
|
45
|
+
mel.gsub!(/#{i}/, (k.to_s)*i.size)
|
46
|
+
}
|
47
|
+
}
|
48
|
+
|
49
|
+
mel.gsub!(/[^\d]/, '0')
|
50
|
+
|
51
|
+
return mel.chars.map(&:to_i)
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
|
56
|
+
# transforme une melodie reduite autour de quelques valeurs neg et pos
|
57
|
+
# en une melodie uniquement positive
|
58
|
+
# RQ : on ne transforme pas 7 en "0" !!
|
59
|
+
def toutDansOctave grille, modulo=7
|
60
|
+
|
61
|
+
return grille.map { |e|
|
62
|
+
if e > modulo and e > 0
|
63
|
+
e-(modulo * (e/modulo))
|
64
|
+
elsif e < 0 and e > modulo
|
65
|
+
(modulo * (e/modulo))-e
|
66
|
+
else
|
67
|
+
e.abs
|
68
|
+
end
|
69
|
+
}
|
70
|
+
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
data/lib/rubySC/musique.rb
CHANGED
@@ -9,18 +9,6 @@ module RubySC_CONST
|
|
9
9
|
## Quelques constantes, notamment pour les rythmes, c'est toujours
|
10
10
|
## plus pratique
|
11
11
|
|
12
|
-
## Je n'ai mis que les rythmes qui me semblaient
|
13
|
-
## les plus connus
|
14
|
-
Rythmes = []
|
15
|
-
|
16
|
-
## Rythmes à 3 notes
|
17
|
-
Rythmes << Pavanne=[2,1,1]
|
18
|
-
Rythmes << Syncopette=[1,2,1]
|
19
|
-
|
20
|
-
Rythmes << Sicilienne=[3,1,2]
|
21
|
-
Rythmes << Chabada=[3,2,1]
|
22
|
-
|
23
|
-
Rythmes << Tresillo=[3,3,2]
|
24
12
|
|
25
13
|
#########
|
26
14
|
|
@@ -143,31 +131,3 @@ module Echelle
|
|
143
131
|
end
|
144
132
|
|
145
133
|
end
|
146
|
-
|
147
|
-
module Rythme
|
148
|
-
|
149
|
-
def self.Tempo vitesse
|
150
|
-
SC.send "TempoClock.default.tempo = #{vitesse}"
|
151
|
-
end
|
152
|
-
|
153
|
-
## s'occupe du premier chiffre de la propriété "dur", c-à-d la vitesse
|
154
|
-
def self.mesure mesure, *voix
|
155
|
-
voix.each do |v|
|
156
|
-
tmp = SC.listeVoix[v.to_s].dur
|
157
|
-
tmp[0] = mesure
|
158
|
-
SC.set true, ({ "dur" => tmp }), v
|
159
|
-
end
|
160
|
-
end
|
161
|
-
|
162
|
-
## s'occupe du deuxième chiffre de la propriété "dur", c-à-d la
|
163
|
-
## gestalt rythmique.
|
164
|
-
|
165
|
-
def self.formule formule, *voix
|
166
|
-
voix.each do |v|
|
167
|
-
tmp = SC.listeVoix[v.to_s].dur
|
168
|
-
tmp[1] = formule
|
169
|
-
SC.set true, ({ "dur" => tmp }), v
|
170
|
-
end
|
171
|
-
end
|
172
|
-
|
173
|
-
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
module Rythme
|
2
|
+
|
3
|
+
|
4
|
+
## Je n'ai mis que les rythmes qui me semblaient
|
5
|
+
## les plus connus
|
6
|
+
Rythmes = []
|
7
|
+
|
8
|
+
## Rythmes à 3 notes
|
9
|
+
Rythmes << Pavanne=[2,1,1]
|
10
|
+
Rythmes << Syncopette=[1,2,1]
|
11
|
+
|
12
|
+
Rythmes << Sicilienne=[3,1,2]
|
13
|
+
Rythmes << Chabada=[3,2,1]
|
14
|
+
|
15
|
+
Rythmes << Tresillo=[3,3,2]
|
16
|
+
|
17
|
+
|
18
|
+
def funkyser
|
19
|
+
|
20
|
+
#replace [cll] par betedecll
|
21
|
+
end
|
22
|
+
|
23
|
+
def calculDernierTemps formuleRythmique, nbMesure=4
|
24
|
+
|
25
|
+
tmp=formuleRythmique.reduce(&:+)
|
26
|
+
lastValue=0
|
27
|
+
if tmp%nbMesure !=0
|
28
|
+
until tmp%nbMesure==0
|
29
|
+
lastValue+=1
|
30
|
+
tmp+=lastValue
|
31
|
+
end
|
32
|
+
end
|
33
|
+
return formuleRythmique << lastValue
|
34
|
+
end
|
35
|
+
|
36
|
+
|
37
|
+
def creerRythme melodie=nil #analyse
|
38
|
+
|
39
|
+
if melodie.nil?
|
40
|
+
return RubySC_CONST::Rythmes.sample
|
41
|
+
end
|
42
|
+
|
43
|
+
rythme = intervallesMel melodie
|
44
|
+
rythme.map! { |inter|
|
45
|
+
case inter.abs
|
46
|
+
when 1
|
47
|
+
note = 1
|
48
|
+
|
49
|
+
else
|
50
|
+
note=2
|
51
|
+
end
|
52
|
+
}
|
53
|
+
rythme << 4
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
|
58
|
+
def self.tempo vitesse
|
59
|
+
SC.send "TempoClock.default.tempo = #{vitesse}"
|
60
|
+
end
|
61
|
+
|
62
|
+
## s'occupe du premier chiffre de la propriété "dur", c-à-d la vitesse
|
63
|
+
def self.mesure mesure, *voix
|
64
|
+
voix.each do |v|
|
65
|
+
tmp = SC.listeVoix[v.to_s].dur
|
66
|
+
tmp[0] = mesure
|
67
|
+
SC.set true, ({ "dur" => tmp }), v
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
## s'occupe du deuxième chiffre de la propriété "dur", c-à-d la
|
72
|
+
## gestalt rythmique.
|
73
|
+
|
74
|
+
def self.formule formule, *voix
|
75
|
+
voix.each do |v|
|
76
|
+
tmp = SC.listeVoix[v.to_s].dur
|
77
|
+
tmp[1] = formule
|
78
|
+
SC.set true, ({ "dur" => tmp }), v
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
data/lib/rubySC/version.rb
CHANGED
data/lib/rubySC/voix.rb
CHANGED
@@ -4,8 +4,8 @@
|
|
4
4
|
|
5
5
|
class Voix
|
6
6
|
|
7
|
-
attr_accessor
|
8
|
-
attr_reader :dur
|
7
|
+
attr_accessor :information, :degree, :octave, :marche, :scale, :amp, :instrument, :name
|
8
|
+
attr_reader :adsr, :dur
|
9
9
|
def initialize nom=nil, options={}
|
10
10
|
|
11
11
|
@information=nil ## cette information sert juste à stocker tout ce
|
@@ -23,7 +23,15 @@ class Voix
|
|
23
23
|
|
24
24
|
SC.listeVoix[@name]=self
|
25
25
|
|
26
|
-
|
26
|
+
@information="en pause \n"
|
27
|
+
self.setDuree options[:dur]
|
28
|
+
|
29
|
+
@adsr=[]
|
30
|
+
if options[:adsr].nil?
|
31
|
+
then self.setADSR 0.2,1,0.9,0.4
|
32
|
+
else
|
33
|
+
selfADSR options[:adsr]
|
34
|
+
end
|
27
35
|
|
28
36
|
if options[:degree].nil?
|
29
37
|
then @degree=Array.new(rand(1..5)) do |x| x=rand(12) end
|
@@ -31,62 +39,67 @@ class Voix
|
|
31
39
|
@degree=options[:degree]
|
32
40
|
end
|
33
41
|
|
34
|
-
if options[
|
42
|
+
if options[:octave].nil?
|
35
43
|
then @octave=4
|
36
44
|
else
|
37
|
-
@octave=options[
|
45
|
+
@octave=options[:octave]
|
38
46
|
end
|
39
47
|
|
40
|
-
if options[
|
48
|
+
if options[:scale].nil?
|
41
49
|
then @scale = "major"
|
42
50
|
else
|
43
|
-
@scale=options[
|
51
|
+
@scale=options[:scale]
|
44
52
|
end
|
45
|
-
if options[
|
53
|
+
if options[:amp].nil?
|
46
54
|
then @amp = "Pwhite(0.2,0.8)"
|
47
55
|
else
|
48
|
-
@amp=options[
|
56
|
+
@amp=options[:amp]
|
49
57
|
end
|
50
58
|
|
51
|
-
if options[
|
59
|
+
if options[:instrument].nil?
|
52
60
|
then @instrument = "default"
|
61
|
+
p "pan!"
|
53
62
|
else
|
54
|
-
|
63
|
+
self.setInstrument options[:instrument]
|
55
64
|
end
|
56
65
|
|
57
66
|
if options[:dur]
|
58
67
|
self.setDuree options[:dur]
|
59
68
|
end
|
60
|
-
|
69
|
+
|
61
70
|
SC.updateScore
|
62
71
|
|
63
72
|
end
|
64
73
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
end
|
70
|
-
case key
|
71
|
-
when "dur"
|
72
|
-
self.setDuree value
|
73
|
-
when "marche"
|
74
|
-
self.setMarche value
|
75
|
-
else
|
76
|
-
self.instance_variable_set "@#{key}", value
|
77
|
-
end
|
78
|
-
end
|
74
|
+
|
75
|
+
def setADSR atk, dec, sus, rel
|
76
|
+
|
77
|
+
@adsr=[(atk/1.0), (dec/1.0), (sus/1.0), (rel/1.0)]
|
79
78
|
SC.updateScore
|
79
|
+
|
80
80
|
end
|
81
81
|
|
82
|
-
def
|
83
|
-
|
84
|
-
|
82
|
+
def setInstrument instrument
|
83
|
+
|
84
|
+
if instrument.is_a? Symbol
|
85
|
+
@information = "le sample utilisé actuellement est #{instrument} \n"
|
86
|
+
SC.sample instrument.to_s
|
87
|
+
@instrument="sampler"
|
85
88
|
else
|
86
|
-
|
87
|
-
end
|
89
|
+
@instrument=instrument
|
90
|
+
end
|
91
|
+
|
88
92
|
end
|
89
93
|
|
94
|
+
|
95
|
+
# def setMarche intervalles
|
96
|
+
# if intervalles.nil?
|
97
|
+
# @root=0
|
98
|
+
# else
|
99
|
+
# @root="Pstutter(#{self.degree.size}, Pseq(#{intervalles}, inf))"
|
100
|
+
# end
|
101
|
+
# end
|
102
|
+
|
90
103
|
def setDuree (duree)
|
91
104
|
|
92
105
|
if duree.nil?
|
@@ -127,9 +140,9 @@ class Voix
|
|
127
140
|
end
|
128
141
|
|
129
142
|
def play
|
143
|
+
SC.updateScore
|
130
144
|
SC.play @name
|
131
|
-
@information="en train de jouer"
|
132
|
-
|
145
|
+
@information="en train de jouer"
|
133
146
|
end
|
134
147
|
|
135
148
|
end
|