rubySC 0.6.0 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|