music_coder 0.7.2 → 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/api/api.rb +31 -0
- data/lib/api/dist.rb +49 -3
- data/lib/api/hit_sq.rb +60 -0
- data/lib/api/mapper.rb +80 -0
- data/lib/audio_output.rb +4 -2
- data/lib/fader.rb +4 -0
- data/lib/logger.rb +6 -7
- data/lib/mixer.rb +2 -0
- data/lib/music_coder.rb +1 -0
- data/lib/snd_dist.rb +5 -2
- data/lib/tests.rb +38 -0
- data/lib/tone.rb +82 -6
- data/lib/tone_part.rb +2 -2
- data/lib/tone_seq.rb +58 -0
- data/lib/wave.rb +1 -1
- metadata +3 -2
data/lib/api/api.rb
CHANGED
@@ -214,4 +214,35 @@ end
|
|
214
214
|
#sets Composer#scale
|
215
215
|
def set_scale sc
|
216
216
|
Composer.scale = sc
|
217
|
+
end
|
218
|
+
# the typical series of commands at the start of a simple new music coder file.
|
219
|
+
def start
|
220
|
+
log_level 1
|
221
|
+
clear
|
222
|
+
set_bpm 128
|
223
|
+
end
|
224
|
+
## return first dist in queue
|
225
|
+
#def root
|
226
|
+
# App.out.snddists[0]
|
227
|
+
#end
|
228
|
+
|
229
|
+
|
230
|
+
def random_sound root_f = 440, len = beat(1), f_range = 0.2, tone_num = 1+rand(16), parts = 1+rand(3), max_delay = 0.6
|
231
|
+
main = len.Dist
|
232
|
+
tone_num.times do |i|
|
233
|
+
main << len.Dist
|
234
|
+
main.last_born << Snd.new
|
235
|
+
snd = main.last_born.snd
|
236
|
+
snd.length = len.to_f
|
237
|
+
delay = rand*max_delay
|
238
|
+
1.times {delay*=rand}
|
239
|
+
snd.toneseq.random(rand(parts), [true,false].sample, delay, 0.333)
|
240
|
+
snd.tone.set_freq root_f
|
241
|
+
range = root_f * f_range
|
242
|
+
snd.tone.set_freq_final root_f - range/2 + rand*range
|
243
|
+
snd.toneseq.amp_reduce tone_num
|
244
|
+
main.last_born.clear_hits
|
245
|
+
main.last_born << delay
|
246
|
+
end
|
247
|
+
main
|
217
248
|
end
|
data/lib/api/dist.rb
CHANGED
@@ -8,7 +8,49 @@ class Dist < Api
|
|
8
8
|
@dist=SndDist.new
|
9
9
|
@hits=HitSq.new
|
10
10
|
@hits.add_parent self
|
11
|
-
persist_hits
|
11
|
+
persist_hits(true)
|
12
|
+
end
|
13
|
+
|
14
|
+
|
15
|
+
#make children with the hits you need for a bar of dubstep percussion. set their #length to mine
|
16
|
+
#this dist has 5 children, in order: bass drum, secondary bass drum, snare, hi hat, second hi hat
|
17
|
+
def dubstep_percussion
|
18
|
+
self << Dist.new # bass drum
|
19
|
+
self.last_born.clear_hits
|
20
|
+
self.last_born << [0.0]
|
21
|
+
self << Dist.new # 2nd bass drum
|
22
|
+
self.last_born.clear_hits
|
23
|
+
self.last_born << [0.75, 0.875] #two last drum hits
|
24
|
+
self << Dist.new # snare
|
25
|
+
self.last_born.clear_hits
|
26
|
+
self.last_born << [0.5] # third beat
|
27
|
+
self << Dist.new # hi hat
|
28
|
+
self.last_born.clear_hits
|
29
|
+
self.last_born << [0.375,0.625] # off beats
|
30
|
+
self << Dist.new # 2nd hi hat
|
31
|
+
self.last_born.clear_hits
|
32
|
+
self.last_born << [0.125,0.875] # off beats
|
33
|
+
set_child_len length
|
34
|
+
self
|
35
|
+
end
|
36
|
+
|
37
|
+
|
38
|
+
#evenly disperse each child across len by modifying the length and hits. uses #length
|
39
|
+
def space_children_across
|
40
|
+
len = self.length
|
41
|
+
branches.times do |i|
|
42
|
+
hit = i.to_f / branches
|
43
|
+
self[i].length = len #(1/branches)* len + hit * len
|
44
|
+
self[i].clear_hits
|
45
|
+
self[i] << hit
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
#sets the length of all children Dist to val
|
50
|
+
def set_child_len val
|
51
|
+
branches.times do |i|
|
52
|
+
self[i].length = val
|
53
|
+
end
|
12
54
|
end
|
13
55
|
|
14
56
|
#add num TonePart to Snd at i's ToneSeq, with my #length as max.
|
@@ -16,6 +58,10 @@ class Dist < Api
|
|
16
58
|
snd(i).toneseq.make(num)
|
17
59
|
end
|
18
60
|
|
61
|
+
#shortcut to create a Mapper, with Mapper#map_to= me
|
62
|
+
def Mapper
|
63
|
+
Mapper.new(self)
|
64
|
+
end
|
19
65
|
# delete another Dist
|
20
66
|
def del todel
|
21
67
|
@dist.snd.delete todel.dist
|
@@ -106,9 +152,9 @@ class Dist < Api
|
|
106
152
|
@dist.tss.count
|
107
153
|
end
|
108
154
|
# (internal use only) copy our hits down to the underlining object
|
109
|
-
def persist_hits
|
155
|
+
def persist_hits(is_def = false)
|
110
156
|
@dist.hits = hits.hits
|
111
|
-
@dist.hits = [0.0] if hits.hits.count == 0
|
157
|
+
@dist.hits = [0.0] if is_def && hits.hits.count == 0
|
112
158
|
self
|
113
159
|
end
|
114
160
|
protected
|
data/lib/api/hit_sq.rb
CHANGED
@@ -38,6 +38,66 @@ class HitSq < Api
|
|
38
38
|
end
|
39
39
|
end
|
40
40
|
public
|
41
|
+
|
42
|
+
def delete_random chance = 0.5
|
43
|
+
to_del = []
|
44
|
+
hits.each do |h|
|
45
|
+
if rand < chance
|
46
|
+
to_del << h
|
47
|
+
end
|
48
|
+
end
|
49
|
+
to_del.each {|d| self.hits.delete d }
|
50
|
+
persist
|
51
|
+
self
|
52
|
+
end
|
53
|
+
|
54
|
+
def trim_start portion=0.25
|
55
|
+
save = []
|
56
|
+
hits.count.times do |i|
|
57
|
+
upto = i.to_f / hits.count
|
58
|
+
if upto >= portion
|
59
|
+
save << hits[i]
|
60
|
+
end
|
61
|
+
end
|
62
|
+
self.hits = save
|
63
|
+
persist
|
64
|
+
end
|
65
|
+
|
66
|
+
def trim_end portion=0.25
|
67
|
+
save = []
|
68
|
+
hits.count.times do |i|
|
69
|
+
upto = i.to_f / hits.count
|
70
|
+
if upto < 1.0 - portion
|
71
|
+
save << hits[i]
|
72
|
+
end
|
73
|
+
end
|
74
|
+
self.hits = save
|
75
|
+
persist
|
76
|
+
end
|
77
|
+
|
78
|
+
def trim_both portion=0.25
|
79
|
+
save = []
|
80
|
+
hits.count.times do |i|
|
81
|
+
upto = i.to_f / hits.count
|
82
|
+
if upto < 1.0 - portion
|
83
|
+
save << hits[i]
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
save2 = []
|
88
|
+
hits.count.times do |i|
|
89
|
+
upto = i.to_f / hits.count
|
90
|
+
if upto >= portion
|
91
|
+
save2 << hits[i]
|
92
|
+
end
|
93
|
+
end
|
94
|
+
self.hits = save&save2
|
95
|
+
persist
|
96
|
+
end
|
97
|
+
#(internal use only)
|
98
|
+
def persist
|
99
|
+
parent.dist.hits = hits if parent
|
100
|
+
end
|
41
101
|
#Adds into #hits.
|
42
102
|
#possible_hits:: number of hits that can occur. Must be int
|
43
103
|
#chance:: chance a hit will be included. range: 0 to 1
|
data/lib/api/mapper.rb
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
#a mapper is a collection of Dist all as long as a Dist being mapped too,
|
2
|
+
#each of these Dist have a child who is getting "mapped" with hits across that length.
|
3
|
+
#everything that you need a mapper for can be
|
4
|
+
#done without one but it is handy, since it is a common patten.
|
5
|
+
class Mapper < Api
|
6
|
+
#the main Dist containing all mappings
|
7
|
+
attr_accessor :dist
|
8
|
+
def initialize(map_to_dist=nil)
|
9
|
+
@dist=Dist.new
|
10
|
+
@len=0
|
11
|
+
self.map_to= map_to_dist if !map_to_dist.nil?
|
12
|
+
end
|
13
|
+
#set the right hits to mix all children one after eachother.
|
14
|
+
#(this can create a dj mix)
|
15
|
+
#mixed_ammount:: the ammount of overlap between children
|
16
|
+
def mix mixed_ammount = 0.25
|
17
|
+
last_start = 0.0
|
18
|
+
dist.branches.times do |i|
|
19
|
+
self[i].clear_hits
|
20
|
+
self[i] << last_start
|
21
|
+
last_start = last_start + (1.0 - mixed_ammount) * (1.0/dist.branches)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
def count
|
25
|
+
dist.branches
|
26
|
+
end
|
27
|
+
#length of each child is set to length of val, and we get added to val
|
28
|
+
#val:: a Dist
|
29
|
+
def map_to= val
|
30
|
+
@len=val.length
|
31
|
+
dist.set_child_len @len
|
32
|
+
val << dist #add me to him
|
33
|
+
end
|
34
|
+
#get a mapper at i from #dist
|
35
|
+
def [] i=0
|
36
|
+
dist[i]
|
37
|
+
end
|
38
|
+
#return last child
|
39
|
+
def last
|
40
|
+
dist.last_born
|
41
|
+
end
|
42
|
+
#return last #mapee
|
43
|
+
def mapee_last
|
44
|
+
last[0]
|
45
|
+
end
|
46
|
+
#get the child of a mapper (the dist to being mapped) at i
|
47
|
+
def mapee i=0
|
48
|
+
dist[i][0]
|
49
|
+
end
|
50
|
+
|
51
|
+
#add dists with the hits you need for a bar of techno percussion.
|
52
|
+
#len:: length of bar
|
53
|
+
#3 children, in order: bass drum, snare, hi hat
|
54
|
+
def techno_percussion len
|
55
|
+
self << len.Dist # bass drum
|
56
|
+
mapee_last.clear_hits
|
57
|
+
mapee_last << 4.eqly_spaced
|
58
|
+
self << len.Dist # snare
|
59
|
+
mapee_last.clear_hits
|
60
|
+
mapee_last << [0.25,0.75]
|
61
|
+
self << len.Dist # hi
|
62
|
+
mapee_last.clear_hits
|
63
|
+
mapee_last << 4.eqly_spaced
|
64
|
+
mapee_last.hits.move(0.125) # offbeats
|
65
|
+
self
|
66
|
+
end
|
67
|
+
|
68
|
+
private
|
69
|
+
# Add Dist to me.
|
70
|
+
def add_single toadd
|
71
|
+
case toadd
|
72
|
+
when Dist
|
73
|
+
dist << @len.Dist
|
74
|
+
dist.last_born << toadd
|
75
|
+
else
|
76
|
+
return false
|
77
|
+
end
|
78
|
+
true
|
79
|
+
end
|
80
|
+
end
|
data/lib/audio_output.rb
CHANGED
@@ -73,7 +73,7 @@ class AudioOutput
|
|
73
73
|
# raise " couldn't find a value... fuck." if found_val.nil?
|
74
74
|
# print percent
|
75
75
|
frames_index += values.count
|
76
|
-
App.logger.print_loading_bar(frames_index, len, percent_complete)
|
76
|
+
App.logger.print_loading_bar(frames_index, len, percent_complete, 50)
|
77
77
|
self.percent_complete = ((frames_index.to_f/len)*100)
|
78
78
|
# values=nil
|
79
79
|
# GC.start
|
@@ -100,11 +100,13 @@ class AudioOutput
|
|
100
100
|
end
|
101
101
|
def print_tail_info total_frames
|
102
102
|
time_taken = App.time_since
|
103
|
-
log 'wrote file: ' + outfile,
|
103
|
+
log 'wrote file: ' + outfile, 2
|
104
104
|
log 'seconds: ' + (total_frames.to_f / Composer.samplerate).round(2).to_s +
|
105
105
|
" (frames: #{(total_frames/1000).round},000)", 2
|
106
106
|
log 'time taken: ' + time_taken.round(2).to_s +
|
107
107
|
" seconds (fps: #{(total_frames/time_taken/1000).round()},000)", 2
|
108
|
+
#end the very last line
|
109
|
+
puts ""
|
108
110
|
end
|
109
111
|
|
110
112
|
end#class
|
data/lib/fader.rb
CHANGED
@@ -15,6 +15,10 @@ def initialize(start=nil,final=nil,exp=0)
|
|
15
15
|
@final = final
|
16
16
|
@exp = exp
|
17
17
|
end
|
18
|
+
# randomize the exp with good values.
|
19
|
+
def rand_exp
|
20
|
+
self.exp = 0.20 * rand(100)
|
21
|
+
end
|
18
22
|
# set #final to a percentage of start
|
19
23
|
def %(percent)
|
20
24
|
self.final = start.to_f*(percent/100.0)
|
data/lib/logger.rb
CHANGED
@@ -2,8 +2,8 @@
|
|
2
2
|
class Logger
|
3
3
|
#higher level means more is logged.
|
4
4
|
#0 means silent.
|
5
|
-
#1 heading and
|
6
|
-
#2 condensed stats and
|
5
|
+
#1 heading and %.
|
6
|
+
#2 condensed stats and written files
|
7
7
|
#3 warnings
|
8
8
|
#4 memory updates and debug info
|
9
9
|
#5 raw data
|
@@ -21,13 +21,12 @@ class Logger
|
|
21
21
|
end
|
22
22
|
|
23
23
|
# a loading bar
|
24
|
-
def print_loading_bar(frames_index, len, percent_complete=nil)
|
24
|
+
def print_loading_bar(frames_index, len, percent_complete=nil, skipped_percent= 0, max= 100)
|
25
25
|
percent = ((frames_index.to_f/len)*100).round(4)
|
26
26
|
percent = percent.round if !percent_complete.nil?
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
App.logger.print_and_flush("__#{percent}%__")
|
27
|
+
percent = skipped_percent + (percent.to_f/100.0)*(max-skipped_percent)
|
28
|
+
if level > 0 && (percent_complete.nil? || (percent_complete.round < percent))
|
29
|
+
App.logger.print_and_flush(" #{percent.round}% ")
|
31
30
|
end
|
32
31
|
percent
|
33
32
|
end
|
data/lib/mixer.rb
CHANGED
data/lib/music_coder.rb
CHANGED
@@ -100,6 +100,7 @@ def self.load_all
|
|
100
100
|
load File.dirname(__FILE__) + '/api/dist.rb'
|
101
101
|
load File.dirname(__FILE__) + '/api/hit_sq.rb'
|
102
102
|
load File.dirname(__FILE__) + '/api/snd.rb'
|
103
|
+
load File.dirname(__FILE__) + '/api/mapper.rb'
|
103
104
|
end
|
104
105
|
|
105
106
|
def self.clear_dir dir_path
|
data/lib/snd_dist.rb
CHANGED
@@ -80,8 +80,11 @@ end
|
|
80
80
|
files.addlist sn.render(into), delay_in_frames
|
81
81
|
end
|
82
82
|
tss.each {|sn| files.addlist sn.render(into), delay_in_frames}
|
83
|
-
App.done
|
84
|
-
|
83
|
+
# puts "#{ App.done} #{App.total}"
|
84
|
+
if !tss.empty?
|
85
|
+
App.done += 1
|
86
|
+
App.logger.print_loading_bar(App.done, App.total, nil, 0, 50)
|
87
|
+
end
|
85
88
|
end
|
86
89
|
files.child_len = (len)
|
87
90
|
files
|
data/lib/tests.rb
CHANGED
@@ -1,6 +1,26 @@
|
|
1
1
|
load File.dirname(__FILE__) + "/music_coder.rb"
|
2
2
|
require "test/unit"
|
3
3
|
|
4
|
+
class TestTones < Test::Unit::TestCase
|
5
|
+
|
6
|
+
def test_setters
|
7
|
+
t= Tone.new
|
8
|
+
t.freq.start = (200)
|
9
|
+
assert_equal(200, t.freq.start)
|
10
|
+
t.freq.final = (20)
|
11
|
+
assert_equal(20, t.freq.final)
|
12
|
+
t.set_freq_final (30)
|
13
|
+
assert_equal(30, t.freq.final)
|
14
|
+
t.set_freq_final(20, false)
|
15
|
+
assert_equal(-180, t.freq.final)
|
16
|
+
assert_equal(-180, t.freq_final)
|
17
|
+
assert_equal(20, t.freq_final(false))
|
18
|
+
t.set_freq(250)
|
19
|
+
assert_equal(-230, t.freq_final)
|
20
|
+
t.set_freq(240)
|
21
|
+
assert_equal(-220, t.freq_final)
|
22
|
+
end
|
23
|
+
end
|
4
24
|
class TestNotes < Test::Unit::TestCase
|
5
25
|
def test_ops
|
6
26
|
n=Note.new(1,5) + (-3)
|
@@ -60,6 +80,24 @@ class TestHitSq < Test::Unit::TestCase
|
|
60
80
|
assert_equal(4, @h.count)
|
61
81
|
end
|
62
82
|
|
83
|
+
def test_hits_trim
|
84
|
+
h=HitSq.new
|
85
|
+
h.eqly_spaced(8)
|
86
|
+
h.trim_end(0.25)
|
87
|
+
assert_equal(([0.0, 0.125, 0.25, 0.375, 0.5, 0.625]), h.hits)
|
88
|
+
h.trim_start(0.25)
|
89
|
+
assert_equal(([0.25, 0.375, 0.5, 0.625]), h.hits)
|
90
|
+
|
91
|
+
|
92
|
+
h.hits = []
|
93
|
+
h << 4.eqly_spaced
|
94
|
+
assert_equal([0.0,0.25,0.5,0.75], h.hits)
|
95
|
+
h.trim_start(0.25)
|
96
|
+
assert_equal([0.25,0.5,0.75], h.hits)
|
97
|
+
h.trim_end(0.34)
|
98
|
+
assert_equal([0.25,0.5], h.hits)
|
99
|
+
end
|
100
|
+
|
63
101
|
def test_hits_move
|
64
102
|
assert_equal(([0.2,0.3,0.4]), @h.hits)
|
65
103
|
@h.move(0.1)
|
data/lib/tone.rb
CHANGED
@@ -21,6 +21,88 @@ def initialize(args = nil)
|
|
21
21
|
init_hash(args)
|
22
22
|
end
|
23
23
|
|
24
|
+
# set frequency #freq#start
|
25
|
+
def set_freq (val)
|
26
|
+
dif = freq.start - val
|
27
|
+
freq.start = val
|
28
|
+
set_freq_final freq_final(false) + dif, false
|
29
|
+
end
|
30
|
+
|
31
|
+
def freq_final(is_relative=true)
|
32
|
+
return is_relative ? freq.final : freq.start + freq.final
|
33
|
+
end
|
34
|
+
|
35
|
+
# random amp.
|
36
|
+
def rand_amp_both(max = 0.8, min = 0.0025)
|
37
|
+
upper = max - min
|
38
|
+
|
39
|
+
val = rand * upper
|
40
|
+
self.amp.start = min + val
|
41
|
+
val = rand * val # can't be more
|
42
|
+
self.set_amp_final (min + val), false
|
43
|
+
self.amp.rand_exp
|
44
|
+
end
|
45
|
+
|
46
|
+
# random ammount of detail in a wave. weighted toward lower values weight times.
|
47
|
+
def rand_detail_both(min = 3, max = 512, weight=2)
|
48
|
+
upper = max - min
|
49
|
+
|
50
|
+
val = rand * upper
|
51
|
+
weight.times {val *= rand}
|
52
|
+
self.wave.detail.start= min + val
|
53
|
+
val = rand * upper
|
54
|
+
weight.times {val *= rand}
|
55
|
+
self.wave.detail.final= min + val
|
56
|
+
# puts "start detail #{val}"
|
57
|
+
# puts "final detail #{val}"
|
58
|
+
self.wave.detail.rand_exp
|
59
|
+
end
|
60
|
+
|
61
|
+
# random ammount of saturation, weighted toward lower values weight times.
|
62
|
+
def rand_sat_both weight=2, max=1.0
|
63
|
+
sat = max
|
64
|
+
weight.times {sat *= rand}
|
65
|
+
self.saturations.start= sat
|
66
|
+
|
67
|
+
sat = max
|
68
|
+
weight.times {sat *= rand}
|
69
|
+
self.saturations.final= sat
|
70
|
+
self.saturations.rand_exp
|
71
|
+
# puts "saturations.start #{saturations.start}"
|
72
|
+
# puts "saturations.final #{saturations.final}"
|
73
|
+
# puts "saturations.x #{saturations.exp}"
|
74
|
+
end
|
75
|
+
|
76
|
+
# random start frequency in range.
|
77
|
+
def rand_freq(min = 12, max = 20_000)
|
78
|
+
upper = max - min
|
79
|
+
val = min + rand*upper
|
80
|
+
self.freq.start = val
|
81
|
+
end
|
82
|
+
|
83
|
+
# random frequencies in range.
|
84
|
+
def rand_freq_both(min = 12, max = 20_000)
|
85
|
+
upper = max - min
|
86
|
+
|
87
|
+
rand_freq min, max
|
88
|
+
val = min + rand*upper # final val
|
89
|
+
self.set_freq_final val, false
|
90
|
+
self.freq.rand_exp
|
91
|
+
# puts "freq.start #{freq.start}"
|
92
|
+
# puts "freq.f #{freq.final}"
|
93
|
+
# puts "freq.x #{freq.exp}"
|
94
|
+
end
|
95
|
+
|
96
|
+
#is_relative:: false for setting it absolute
|
97
|
+
def set_freq_final fq, is_relative=true
|
98
|
+
self.freq.final = is_relative ? fq : fq - freq.start
|
99
|
+
end
|
100
|
+
|
101
|
+
#is_relative:: false for setting it absolute
|
102
|
+
def set_amp_final val, is_relative=true
|
103
|
+
self.amp.final = is_relative ? val : val - amp.start
|
104
|
+
end
|
105
|
+
|
24
106
|
# set saturation for both start and end
|
25
107
|
def saturation= val
|
26
108
|
wave.saturation= val
|
@@ -100,12 +182,6 @@ def out
|
|
100
182
|
data
|
101
183
|
end
|
102
184
|
|
103
|
-
# setting it absolute
|
104
|
-
def set_freq_final_no_relative(final)
|
105
|
-
dif=final - freq.start
|
106
|
-
freq.final=dif
|
107
|
-
end
|
108
|
-
|
109
185
|
# set #freq based off a Note
|
110
186
|
def note=(note)
|
111
187
|
freq.start = note.freq
|
data/lib/tone_part.rb
CHANGED
data/lib/tone_seq.rb
CHANGED
@@ -2,10 +2,63 @@
|
|
2
2
|
class ToneSeq
|
3
3
|
#Array of TonePart
|
4
4
|
attr_accessor :toneparts
|
5
|
+
#when joined, a tone sequence makes the end of each tone
|
6
|
+
#the same as the start of the next one.
|
7
|
+
#this creates a smooth sound.
|
8
|
+
#todo
|
9
|
+
def join
|
10
|
+
toneparts.count.times do |i|
|
11
|
+
# if more after me, do it
|
12
|
+
if i+1 < toneparts.count
|
13
|
+
me = toneparts[i].tone(0)
|
14
|
+
nxt = toneparts[i+1].tone(0)
|
15
|
+
me.detail.final = nxt.detail.start
|
16
|
+
me.saturations.final = nxt.saturations.start
|
17
|
+
me.set_freq_final( nxt.freq.start, false)
|
18
|
+
me.set_amp_final( nxt.amp.start, false)
|
19
|
+
|
20
|
+
me = toneparts[i].tone(1)
|
21
|
+
nxt = toneparts[i+1].tone(1)
|
22
|
+
me.detail.final = nxt.detail.start
|
23
|
+
me.saturations.final = nxt.saturations.start
|
24
|
+
me.set_freq_final( nxt.freq.start, false)
|
25
|
+
me.set_amp_final( nxt.amp.start, false)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
5
30
|
def initialize()
|
6
31
|
@toneparts = []
|
7
32
|
make(1)
|
8
33
|
end
|
34
|
+
|
35
|
+
#random everything
|
36
|
+
def random extra_detail = 5, even = false, delay=0, start_amp = 0.5,
|
37
|
+
max_f = 2000, min_f = 120, max_sat=0.2, min_detail=50
|
38
|
+
make(extra_detail) # sets the lens evenly.
|
39
|
+
frames_left = self.frames - self.frames.to_f*delay #- extra_detail+1 #minus a little so it must have 1 frame
|
40
|
+
toneparts.count.times do |i|
|
41
|
+
# sets the lens randomly.
|
42
|
+
portion = frames_left * rand
|
43
|
+
# puts "portion #{portion}"
|
44
|
+
if i == toneparts.count
|
45
|
+
portion = frames_left
|
46
|
+
end
|
47
|
+
frames_left -= 1+portion
|
48
|
+
toneparts[i].tone.frames = 1+portion if !even
|
49
|
+
#
|
50
|
+
toneparts[i].tone.rand_sat_both 3, max_sat
|
51
|
+
toneparts[i].tone.rand_freq_both(min_f, max_f)
|
52
|
+
toneparts[i].tone.rand_detail_both min_detail
|
53
|
+
max_amp = start_amp
|
54
|
+
if i>0 # it can't be higher than the last amp
|
55
|
+
max_amp = toneparts[i-1].tone.amp.start
|
56
|
+
end
|
57
|
+
toneparts[i].tone.rand_amp_both max_amp, max_amp * 0.75 # not much lower
|
58
|
+
end
|
59
|
+
join
|
60
|
+
end
|
61
|
+
|
9
62
|
#return the total frames of all toneparts combined.
|
10
63
|
def frames
|
11
64
|
total=0
|
@@ -50,5 +103,10 @@ class ToneSeq
|
|
50
103
|
files.write data
|
51
104
|
files
|
52
105
|
end
|
106
|
+
|
107
|
+
#reduce amp of all tones by this val
|
108
|
+
def amp_reduce val
|
109
|
+
toneparts.each { |tp| tp.amp_mult(1.0/val) }
|
110
|
+
end
|
53
111
|
|
54
112
|
end
|
data/lib/wave.rb
CHANGED
@@ -5,7 +5,7 @@ class Wave
|
|
5
5
|
# Fader.final is at the end. nil means same as wave start
|
6
6
|
attr_accessor :detail
|
7
7
|
#saturation effect (a random fluctuation on each data point to the cycle).
|
8
|
-
#
|
8
|
+
#the ammount of saturation is higher is more, 0 is none. range: 0 to 1.
|
9
9
|
attr_accessor :saturations
|
10
10
|
# hack to dramatically speed it up when on.
|
11
11
|
attr_accessor :cache_wave, :old_wave
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: music_coder
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.9.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -48,6 +48,7 @@ files:
|
|
48
48
|
- lib/audio.rb
|
49
49
|
- lib/fader.rb
|
50
50
|
- lib/api/snd.rb
|
51
|
+
- lib/api/mapper.rb
|
51
52
|
- lib/api/hit_sq.rb
|
52
53
|
- lib/api/dist.rb
|
53
54
|
- lib/api/api.rb
|
@@ -79,7 +80,7 @@ rubyforge_project:
|
|
79
80
|
rubygems_version: 1.8.23
|
80
81
|
signing_key:
|
81
82
|
specification_version: 3
|
82
|
-
summary: An application to programmatically create music
|
83
|
+
summary: An application to programmatically create music by coding.
|
83
84
|
test_files:
|
84
85
|
- lib/tests.rb
|
85
86
|
has_rdoc: true
|