music_coder 0.7.2 → 0.9.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.
- 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
|